Compare commits

..

10 Commits

Author SHA1 Message Date
Tyrel Souza
1bf0e8b94e remove find or create by name 2014-02-13 15:45:12 -05:00
Tyrel Souza
f251500aa4 added rake command 2014-02-13 15:44:56 -05:00
Tyrel Souza
5a8fd39e6b added style and js 2014-02-13 14:19:41 -05:00
Tyrel Souza
00aa985fce added assets, etc 2014-02-13 12:12:02 -05:00
Tyrel Souza
000d19eaf9 store 2014-02-13 11:02:57 -05:00
Tyrel Souza
a946ea07ef cleanup html styles a bit 2014-02-13 01:07:35 -05:00
Tyrel Souza
5820d816de clean up javascript, added m2m 2014-02-13 00:47:27 -05:00
Tyrel Souza
a13856ea64 Added m2m on list entry and localeze_categories 2014-02-13 00:31:36 -05:00
Tyrel Souza
7df136799a added activeadmin, javascript, css, list entry 2014-02-13 00:07:45 -05:00
Tyrel Souza
2e64e49264 Real localeze, not the symlink 2014-01-14 01:49:45 -05:00
36 changed files with 1136 additions and 12 deletions

13
Gemfile
View File

@ -2,14 +2,19 @@ source "https://rubygems.org"
gem "rails", "3.2.12"
gem "sqlite3"
gem "meta_search", '>= 1.1.0.pre'
gem "rails_config"
gem "savon", "~> 2.0"
gem "gyoku", "~> 1.0"
gem "pry"
group :assets do
gem "coffee-rails", "~> 3.2.1"
gem "gyoku", "~> 1.0"
gem "jquery-rails"
gem "rails_config"
gem 'jquery-rails', "2.3.0"
gem "sass-rails", "~> 3.2.3"
gem "savon", "~> 2.0"
gem "uglifier", ">= 1.0.3"
gem "gemsurance"
gem "chosen-rails"
gem "twitter-bootstrap-rails"
gem "maskedinput-rails"
end

View File

@ -33,6 +33,13 @@ GEM
nokogiri (>= 1.4.0)
arel (3.0.3)
builder (3.0.4)
chosen-rails (1.1.0)
coffee-rails (>= 3.2)
compass-rails (>= 1.1.2)
railties (>= 3.0)
sass-rails (>= 3.2)
chunky_png (1.3.0)
coderay (1.1.0)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
@ -40,8 +47,15 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.6.3)
compass (0.12.2)
chunky_png (~> 1.2)
fssm (>= 0.2.7)
sass (~> 3.1)
compass-rails (1.1.3)
compass (>= 0.12.2)
erubis (2.7.0)
execjs (2.0.2)
fssm (0.2.10)
gemsurance (0.1.4)
bundler (~> 1.2)
git (~> 1.2)
@ -54,7 +68,7 @@ GEM
rubyntlm (~> 0.3.2)
i18n (0.6.9)
journey (1.0.4)
jquery-rails (3.0.4)
jquery-rails (2.3.0)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
json (1.8.1)
@ -62,13 +76,26 @@ GEM
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
maskedinput-rails (1.3.1.0)
meta_search (1.1.3)
actionpack (~> 3.1)
activerecord (~> 3.1)
activesupport (~> 3.1)
polyamorous (~> 0.5.0)
method_source (0.8.2)
mime-types (1.25.1)
mini_portile (0.5.2)
multi_json (1.8.4)
nokogiri (1.6.1)
mini_portile (~> 0.5.0)
nori (2.3.0)
polyamorous (0.5.0)
activerecord (~> 3.0)
polyglot (0.3.3)
pry (0.9.12.6)
coderay (~> 1.0)
method_source (~> 0.8)
slop (~> 3.4)
rack (1.4.5)
rack-cache (1.2)
rack (>= 0.4)
@ -110,6 +137,7 @@ GEM
nokogiri (>= 1.4.0)
nori (~> 2.3.0)
wasabi (~> 3.2.2)
slop (3.4.7)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)
@ -121,6 +149,11 @@ GEM
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
twitter-bootstrap-rails (2.2.8)
actionpack (>= 3.1)
execjs
rails (>= 3.1)
railties (>= 3.1)
tzinfo (0.3.38)
uglifier (2.4.0)
execjs (>= 0.3.0)
@ -134,13 +167,18 @@ PLATFORMS
ruby
DEPENDENCIES
chosen-rails
coffee-rails (~> 3.2.1)
gemsurance
gyoku (~> 1.0)
jquery-rails
jquery-rails (= 2.3.0)
maskedinput-rails
meta_search (>= 1.1.0.pre)
pry
rails (= 3.2.12)
rails_config
sass-rails (~> 3.2.3)
savon (~> 2.0)
sqlite3
twitter-bootstrap-rails
uglifier (>= 1.0.3)

2
TODO Normal file
View File

@ -0,0 +1,2 @@
TODO:
Get all localeze categories so I can add a "has_many:" in the ListEntry

View File

@ -12,4 +12,8 @@
//
//= require jquery
//= require jquery_ujs
//= require twitter/bootstrap
//= require maskedinput
//= require chosen-jquery
//= require_tree .

View File

@ -0,0 +1,3 @@
jQuery ->
$("a[rel~=popover], .has-popover").popover()
$("a[rel~=tooltip], .has-tooltip").tooltip()

View File

@ -0,0 +1,66 @@
$ ->
$("#list_entry_localeze_categories").chosen max_selected_options: 3, placeholder_text_multiple: "Select up to Three"
$("#how").click ->
$(".how").toggle()
elem = $("#chars")
$("#set_all").click all_days_same
$("#set_MF").click all_MF
$("#set_clear").click clear_times
$.each [
"sun"
"mon"
"tues"
"wednes"
"thurs"
"fri"
"satur"
], (i, day) ->
$("#hours_#{day}day_close").insertAfter "#hours_#{day}_open"
$("#hours_sunday_close").after "&nbsp;&nbsp; <a href='#' id='set_all'>[Apply To All]</a>"
$("#hours_monday_close").after "&nbsp;&nbsp; <a href='#' id='set_MF'>[Set Monday-Friday]</a>"
$("#set_all").click all_days_same
$("#set_MF").click all_MF
$("#set_clear").click clear_times
for i in [0..9]
$("#payment_types_commadelimited_#{i}").click clear_payment_types
$("#list_entry_Phone").mask "(999) 999-9999"
$("#list_entry_AltNumber").mask "(999) 999-9999"
$("#list_entry_Fax").mask "(999) 999-9999"
clear_payment_types = ->
unchecked = true
for i in [1...9]
$("#payment_types_commadelimited_#{i}").prop "checked", ""
return
check_payment_types = ->
unchecked = true
for i in [1...9]
if $("#payment_types_commadelimited_#{i}").is(":checked")
$("#payment_types_commadelimited_0").prop "checked", ""
unchecked = false
$("#payment_types_commadelimited_0").prop "checked", "checked" if unchecked
all_days_same = ->
open_time = $("#hours_sunday_open").val()
close_time = $("#hours_sunday_close").val()
$("select[id*=day_open]").val open_time
$("select[id*=day_close]").val close_time
false
all_MF = ->
open_time = $("#hours_monday_open").val()
close_time = $("#hours_monday_close").val()
$("select[id*=day_open]:not(select[id*=sunday]):not(select[id*=saturday])").val open_time
$("select[id*=day_close]:not(select[id*=sunday]):not(select[id*=saturday])").val close_time
false
clear_times = ->
open_time = ""
close_time = ""
$("select[id*=day_open]").val open_time
$("select[id*=day_close]").val close_time

View File

@ -9,5 +9,9 @@
* compiled file, but it's generally better to create a new file per style scope.
*
*= require_self
*= require chosen
*= require list_entry
*= require bootstrap_and_overrides
*= require superhero.min
*= require_tree .
*/

View File

@ -0,0 +1,7 @@
/*
=require twitter-bootstrap-static/bootstrap
Use Font Awesome icons (default)
To use Glyphicons sprites instead of Font Awesome, replace with "require twitter-bootstrap-static/sprites"
=require twitter-bootstrap-static/fontawesome
*/

View File

@ -0,0 +1,132 @@
html, body {
height: 100%;
}
.tab-content {
overflow: none ! important;
}
.nav {
margin-bottom: 0px ! important;
}
.how {
margin-bottom: 3px ! important;
}
.chosen-container-multi {
width: 314px ! important;
}
.required label:before {
content: "* ";
color: #f00;
}
.control-group.required .controls label {
font-weight: normal;
&:before {
content: none;
}
}
input[type="text"] {
width: 300px ! important;
height: 1.8em;
}
.controls select {
height: 1.8em;
}
select[id*="hours"] {
width: 100px;
}
label[for*="close"] {
display: none;
}
.help-block {
font-size: 11px;
}
.required {
label {
font-weight: bold;
}
> input {
background-color: whiteSmoke;
}
}
#wrap {
min-height: 100%;
height: auto !important;
height: 100%;
/* Negative indent footer by it's height */
margin: 0 auto -90px;
}
#push {
height: 90px;
}
#footer {
height: 90px;
/*padding-top: 20px;*/
background-color: #f5f5f5;
text-align: center;
}
#how {
cursor: hand;
cursor: pointer;
float: right;
&:hover {
color: #fff;
}
}
.how {
display: none;
}
.page-header {
margin-bottom: 0px;
}
.checkmark {
font-size: 72pt;
color: #00dd00;
}
.xmark {
font-size: 72pt;
color: dd0000;
}
.menu {
margin: 0;
padding: 0;
}
label.error {
padding-top: 4px;
color: #c76e6d;
}
div.staging-container {
bottom: 0px;
position: fixed;
width: 100%;
z-index: 52;
div {
background: rgba(0, 124, 204, 0.95);
text-align: center;
font-weight: bold;
width: 100%;
margin: auto;
padding: 6px 0 5px 0;
}
}

View File

@ -0,0 +1,31 @@
body { background-color: #5f7395; color: #333; }
body, p, ol, ul, td {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 13px;
line-height: 18px;
}
pre {
background-color: #eee;
padding: 10px;
font-size: 11px;
}
a { color: #000; }
a:visited { color: #666; }
a:hover { color: #fff; background-color:#000; }
#main {
background-color: #fff;
border: solid #000 1px;
margin: 5em;
height: 30em;
padding: 1em;
}
#notice {
background-color: #e1facf;
border: solid #97C36d 1px;
padding: 0.5em;
}

View File

@ -0,0 +1,29 @@
class ListEntriesController < ApplicationController
def new
@listentry = ListEntry.new
end
def create
ListEntry.new(listentry_params)
end
private
def listentry_params
params.require(:user).permit(:Address,
:AltNumber,
:BusinessName,
:City,
:CreditCards,
:Department,
:Fax,
:HoursOfOperation,
:LogoImage,
:Phone,
:State,
:URL,
:UnstructuredTerms,
:Zip,
:eMail)
end
end

View File

@ -2,7 +2,6 @@ class LocalezeController < ApplicationController
def initialize
end
private
def authenticate
response = @client.call(:authenticate, message:

View File

@ -0,0 +1,54 @@
module ListEntryHelper
def hours_hash
{
'6:00 AM' => '0600',
'6:30 AM' => '0630',
'7:00 AM' => '0700',
'7:30 AM' => '0730',
'8:00 AM' => '0800',
'8:30 AM' => '0830',
'9:00 AM' => '0900',
'9:30 AM' => '0930',
'10:00 AM' => '1000',
'10:30 AM' => '1030',
'11:00 AM' => '1100',
'11:30 AM' => '1130',
'12:00 PM' => '1200',
'12:30 PM' => '1230',
'1:00 PM' => '1300',
'1:30 PM' => '1330',
'2:00 PM' => '1400',
'2:30 PM' => '1430',
'3:00 PM' => '1500',
'3:30 PM' => '1530',
'4:00 PM' => '1600',
'4:30 PM' => '1630',
'5:00 PM' => '1700',
'5:30 PM' => '1730',
'6:00 PM' => '1800',
'6:30 PM' => '1830',
'7:00 PM' => '1900',
'7:30 PM' => '1930',
'8:00 PM' => '2000',
'8:30 PM' => '2030',
'9:00 PM' => '2100',
'9:30 PM' => '2130',
'10:00 PM' => '2200',
'10:30 PM' => '2230',
'11:00 PM' => '2300',
'11:30 PM' => '2330',
'12:00 AM' => '0000',
'12:30 AM' => '0030',
'1:00 AM' => '0100',
'1:30 AM' => '0130',
'2:00 AM' => '0200',
'2:30 AM' => '0230',
'3:00 AM' => '0300',
'3:30 AM' => '0330',
'4:00 AM' => '0400',
'4:30 AM' => '0430',
'5:00 AM' => '0500',
'5:30 AM' => '0530',
}
end
end

View File

View File

@ -1,3 +1,25 @@
class ListEntry < ActiveRecord::Base
attr_accessible :Address, :AltNumber, :BusinessName, :City, :CreditCards, :Department, :Fax, :HoursOfOperation, :LogoImage, :Phone, :State, :URL, :UnstructuredTerms, :Zip, :eMail
attr_accessible :form_hash,
:success,
:Address,
:AltNumber,
:BusinessName,
:City,
:CreditCards,
:Department,
:Fax,
:HoursOfOperation,
:LogoImage,
:Phone,
:State,
:URL,
:UnstructuredTerms,
:Zip,
:eMail
has_and_belongs_to_many :localeze_categories
end

View File

@ -1 +0,0 @@
/home/tsouza/code/ruby/localeze_api/localeze.rb

View File

@ -0,0 +1,5 @@
class LocalezeCategory < ActiveRecord::Base
attr_accessible :name
has_and_belongs_to_many :list_entries
end

View File

@ -0,0 +1,103 @@
require 'cgi'
class LocalezeClient
def initialize
@client = Savon.client(wsdl: Settings.localeze_wsdl, namespace: Settings.localeze_wsdl, pretty_print_xml: true)
end
# Check that a supplied listing is available to claim.
def check(listing)
value = record_to_xml(listing, true)
query = @client.call(:query, message: message(:add, value, :check))
result = get_deep_value(query)['Response']
check_successful?(result['ErrorCode']) ? true : result['ErrorMessage']
end
# Create the supplied listing.
def create(listing)
value = record_to_xml(listing, true)
query = @client.call(:query, message: message(:add, value, :create))
result = get_deep_value(query)['Response']
status = create_successful?(result)
handle_status(status)
end
# Cache the categories
def categories
@_categories ||= categories! # Memoizing
end
private
# Cached methods
# make a call to localeze to get a list of all the categories available
def categories!
query = @client.call(:query, message: message(:query, 'ACTIVEHEADINGS', :category))
headings = get_deep_value(query)['ActiveHeadings']['Heading']
end
# Not sure why, but Localeze returns either an ErrorMessage or a Validator with a Resolution if there's an error.
# This will get the error code regardless of where it is in one of these locations
def get_errors(result)
if result.has_key?('ErrorMessage')
return result['ErrorMessage']
elsif result.has_key?('Validators')
return result['Validators']['Resolution']
end
end
# The value that localeze gives us is very deep, this method
# cleans that up a little in the implementation depending on the element
def get_deep_value(query)
Hash.from_xml(query.to_hash[:query_response][:response][:result][:element][:value].to_s)
end
# This is a helper method to generate the giant dictionary you send as a message.
# Rather than needing to supply this dictionary every time, all you need to supply is the Action Key,
# the value to send, and the ElementId
def message(key, value, element)
{origination: { username: Settings.localeze_username, password: Settings.localeze_password },
serviceId: Settings.localeze_serviceid,
transId: 1,
elements: {id: Settings.localeze_ids[element]},
serviceKeys: {serviceKey: { id: Settings.localeze_ids[key], value: value} }
}
end
# This will wrap a record hash into the xml format required by localeze, also escape if needed.
# The reason it doesn't just use to_xml, is because we needed the "Edition" attribute.
def record_to_xml(record, escape = false)
bmps = {'BPMSPost' => {'Record' => record }, :attributes! => { 'BPMSPost' => { 'Edition' => '1.1' }}}
Gyoku.xml(bmps, {:key_converter => :none})
end
# Check that the error codes returned are Success codes.
def check_successful? code
Settings[:localeze_check_success].include? code
end
def create_successful? result
if Settings[:localeze_create_success].include? result['ErrorCode']
if result['ErrorMessage']
return {passes: false, message: result['ErrorMessage']}
elsif result['Validators'].is_a?(Array)
return [passes: true, message: result['Validators'].map{|v| v['Resolution']} * "\n"]
elsif result['Validators']
return [passes: true, message: result['Validators']['Resolution']]
end
else
return true
end
end
def handle_status(status)
if status.is_a?(Hash)
if status[:passes]
puts "Was submitted, but needs validation on site: #{status[:message]}"
else
puts "Was not submitted, Please fix: #{status[:message]}"
end
else
puts "Successful"
end
end
end

View File

@ -0,0 +1 @@
hi

View File

@ -2,12 +2,12 @@
<html>
<head>
<title>Listpush</title>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>

View File

@ -0,0 +1,166 @@
<div id="wrap">
<form id="form" class="form-horizontal" action="." method="POST">
<div class="container">
<div class="page-header">
<h1>Add A Listing</h1>
</div>
<h5 id="how">How does this work?</h5>
<ul class="nav nav-tabs menu">
<li class="active"><a href="#tab1" data-toggle="tab">General Information</a></li>
<li><a href="#tab2" data-toggle="tab">Business Hours</a></li>
</ul>
<div class="well how">
<p>This tool is intended to streamline the process of adding listings. Fill in the information below just once, and well send it along to Localeze.</p>
<p>After you submit a listing, all listing account management still needs to take place within Localeze. For example, if you need to modify, verify, or access a listing for any reason, you must log in to Localeze separately and manage listings from those locations.</p>
</div>
<div class="tab-content">
<%= form_for @listentry do |f| %>
<div class="tab-pane active" id="tab1">
<div class="well">
<div class="control-group required">
<%= f.label :BusinessName, "Business Name", {class: "control-label"} %>
<div class="controls">
<%= f.text_field :BusinessName %>
</div>
</div>
<div class="control-group">
<%= f.label :Department, {class: "control-label"} %>
<div class="controls">
<%= f.text_field :Department %>
</div>
</div>
<div class="control-group">
<%= f.label :localeze_categories, "Localeze Categories", {class: "control-label"} %>
<div class="controls">
<%= f.collection_select(:localeze_categories , LocalezeCategory.find(:all), :id , :name, {}, { :multiple => true, :size => 3, class: 'fuckingworkdick' }) %>
</div>
</div>
<div class="control-group">
<%= f.label :City, {class: "control-label"} %>
<div class="controls">
<%= f.text_field :City %>
</div>
</div>
<div class="control-group">
<%= f.label :State, {class: "control-label"} %>
<div class="controls">
<%= f.text_field :State %>
</div>
</div>
<div class="control-group">
<%= f.label :Zip, {class: "control-label"} %>
<div class="controls">
<%= f.text_field :Zip %>
</div>
</div>
<div class="control-group">
<%= f.label :Phone, {class: "control-label"} %>
<div class="controls">
<%= f.text_field :Phone %>
</div>
</div>
<div class="control-group">
<%= f.label :AltNumber, "Alternate Phone Number", {class: "control-label"} %>
<div class="controls">
<%= f.text_field :AltNumber %>
</div>
</div>
<div class="control-group">
<%= f.label :Fax, {class: "control-label"} %>
<div class="controls">
<%= f.text_field :Fax %>
</div>
</div>
<div class="control-group">
<%= f.label :eMail, "e-Mail", {class: "control-label"} %>
<div class="controls">
<%= f.text_field :eMail %>
</div>
</div>
<div class="control-group">
<%= f.label :LogoImage, {class: "control-label"} %>
<div class="controls">
<%= f.text_field :LogoImage %>
</div>
</div>
<div class="control-group">
<%= f.label :URL, {class: "control-label"} %>
<div class="controls">
<%= f.text_field :URL %>
</div>
</div>
<div class="control-group">
<%= f.label :CreditCards, {class: "control-label"} %>
<div class="controls">
<%= f.text_field :CreditCards %>
</div>
</div>
<div class="control-group">
<%= f.label :UnstructuredTerms, {class: "control-label"} %>
<div class="controls">
<%= f.text_field :UnstructuredTerms %>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="tab2">
<div class="well">
<h6><a href='#' id='set_clear'>[Clear]</a></h6>
<%= select( "hours_sunday", "open", hours_hash) %>
<%= select( "hours_sunday", "close", hours_hash) %><br>
<%= select( "hours_monday", "open", hours_hash) %>
<%= select( "hours_monday", "close", hours_hash) %><br>
<%= select( "hours_tuesday", "open", hours_hash) %>
<%= select( "hours_tuesday", "close", hours_hash) %><br>
<%= select( "hours_wednesday", "open", hours_hash) %>
<%= select( "hours_wednesday", "close", hours_hash) %><br>
<%= select( "hours_thursday", "open", hours_hash) %>
<%= select( "hours_thursday", "close", hours_hash) %><br>
<%= select( "hours_friday", "open", hours_hash) %>
<%= select( "hours_friday", "close", hours_hash) %><br>
<%= select( "hours_saturday", "open", hours_hash) %>
<%= select( "hours_saturday", "close", hours_hash) %><br>
</div>
</div>
<% end %>
</div>
</div>
<div id="push"></div>
</div>
<div id="footer">
<div class="container">
<h4> When you're complete with all tabs... </h4>
<button id="submit" name="submit" class="btn btn-primary">Submit Listing</button>
</div>
</div>
</form>

View File

@ -15,6 +15,8 @@ Listpush::Application.configure do
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
@ -34,4 +36,6 @@ Listpush::Application.configure do
# Expands the lines which load the assets
config.assets.debug = true
end

View File

@ -0,0 +1,59 @@
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
en:
devise:
confirmations:
confirmed: "Your account was successfully confirmed."
send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes."
failure:
already_authenticated: "You are already signed in."
inactive: "Your account is not activated yet."
invalid: "Invalid email or password."
locked: "Your account is locked."
last_attempt: "You have one more attempt before your account will be locked."
not_found_in_database: "Invalid email or password."
timeout: "Your session expired. Please sign in again to continue."
unauthenticated: "You need to sign in or sign up before continuing."
unconfirmed: "You have to confirm your account before continuing."
mailer:
confirmation_instructions:
subject: "Confirmation instructions"
reset_password_instructions:
subject: "Reset password instructions"
unlock_instructions:
subject: "Unlock Instructions"
omniauth_callbacks:
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
success: "Successfully authenticated from %{kind} account."
passwords:
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
send_instructions: "You will receive an email with instructions about how to reset your password in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
updated: "Your password was changed successfully. You are now signed in."
updated_not_active: "Your password was changed successfully."
registrations:
destroyed: "Bye! Your account was successfully cancelled. We hope to see you again soon."
signed_up: "Welcome! You have signed up successfully."
signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please open the link to activate your account."
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm link to finalize confirming your new email address."
updated: "You updated your account successfully."
sessions:
signed_in: "Signed in successfully."
signed_out: "Signed out successfully."
unlocks:
send_instructions: "You will receive an email with instructions about how to unlock your account in a few minutes."
send_paranoid_instructions: "If your account exists, you will receive an email with instructions about how to unlock it in a few minutes."
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
errors:
messages:
already_confirmed: "was already confirmed, please try signing in"
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
expired: "has expired, please request a new one"
not_found: "not found"
not_locked: "was not locked"
not_saved:
one: "1 error prohibited this %{resource} from being saved:"
other: "%{count} errors prohibited this %{resource} from being saved:"

View File

@ -0,0 +1,18 @@
# Sample localization file for English. Add more files in this directory for other locales.
# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
en:
helpers:
actions: "Actions"
links:
back: "Back"
cancel: "Cancel"
confirm: "Are you sure?"
destroy: "Delete"
new: "New"
edit: "Edit"
titles:
edit: "Edit %{model}"
save: "Save %{model}"
new: "New %{model}"
delete: "Delete %{model}"

View File

@ -1,2 +1,4 @@
Listpush::Application.routes.draw do
resources :list_entries
end

View File

@ -0,0 +1,9 @@
class CreateLocalezeCategories < ActiveRecord::Migration
def change
create_table :localeze_categories do |t|
t.string :name, :limit => 256
t.timestamps
end
end
end

View File

@ -0,0 +1,14 @@
class CreateListEntryLocalezeCategoryJoinTable < ActiveRecord::Migration
def self.up
create_table :list_entries_localeze_categories, :id => false do |t|
t.integer :list_entry_id
t.integer :localeze_category_id
end
add_index :list_entries_localeze_categories, [:list_entry_id, :localeze_category_id], name: "listentries_localezecategory_index"
end
def self.down
drop_table :list_entries_localeze_categories
end
end

View File

@ -11,7 +11,40 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20140114064456) do
ActiveRecord::Schema.define(:version => 20140213052627) do
create_table "active_admin_comments", :force => true do |t|
t.string "resource_id", :null => false
t.string "resource_type", :null => false
t.integer "author_id"
t.string "author_type"
t.text "body"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "namespace"
end
add_index "active_admin_comments", ["author_type", "author_id"], :name => "index_active_admin_comments_on_author_type_and_author_id"
add_index "active_admin_comments", ["namespace"], :name => "index_active_admin_comments_on_namespace"
add_index "active_admin_comments", ["resource_type", "resource_id"], :name => "index_admin_notes_on_resource_type_and_resource_id"
create_table "admin_users", :force => true do |t|
t.string "email", :default => "", :null => false
t.string "encrypted_password", :default => "", :null => false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", :default => 0, :null => false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "admin_users", ["email"], :name => "index_admin_users_on_email", :unique => true
add_index "admin_users", ["reset_password_token"], :name => "index_admin_users_on_reset_password_token", :unique => true
create_table "list_entries", :force => true do |t|
t.string "BusinessName", :limit => 100
@ -35,4 +68,17 @@ ActiveRecord::Schema.define(:version => 20140114064456) do
t.string "form_hash", :limit => 16
end
create_table "list_entries_localeze_categories", :id => false, :force => true do |t|
t.integer "list_entry_id"
t.integer "localeze_category_id"
end
add_index "list_entries_localeze_categories", ["list_entry_id", "localeze_category_id"], :name => "listentries_localezecategory_index"
create_table "localeze_categories", :force => true do |t|
t.string "name", :limit => 256
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
end

View File

@ -0,0 +1,137 @@
// var reg_business_name = /[^A-Za-z0-9!?. \-,'&():\|\"+@%]+/g;
// var reg_zip = /[^0-9]+/g;
// var reg_addr = /[^A-Za-z0-9ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿŒœŠšŸ .\-'`,#\/]+/g;
// var reg_city = /[^A-Za-z0-9ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿŒœŠšŸ .\-'`]+/g;
// var reg_name = /[^A-Za-z1-9ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿŒœŠšŸ .\-'`,]+/g;
// var reg_desc = /[^A-Za-z0-9ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿŒœŠšŸ!?. \-,'\/&():|\"+@%$£]+/g;
// var reg_comma = /[^A-Za-z0-9ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿŒœŠšŸ!?. \-,\/&#']+/g;
// var reg_tollfree = /^(\+?1)?(8(00|55|66|77|88)[2-9]\d{6})/;
// var validate_via_regex = function(str, regex){
// var matches = str.match(regex);
// if (matches === null){
// return true;
// } else {
// return matches;
// }
// };
// var validations = function(){
// $("input.remove_title").attr("title", "");
// $("#form").validate({
// rules: {
// business_name: "reg_business_name",
// address_line_1: "reg_addr",
// address_line_2: "reg_addr",
// city: "reg_city",
// business_description: "reg_desc",
// primary_contact_name: "reg_name",
// postal_code: "reg_zip",
// business_email_address: "email",
// business_website: "url",
// social_media_link: "url",
// products_commadelimited: "reg_comma",
// keyword_specialties_commadelimited: "reg_comma",
// areas_served_commadelimited: "reg_comma",
// professional_associations_commadelimited: "reg_comma",
// services_commadelimited: "reg_comma",
// logo_url: "url",
// photo_url_1: "url",
// phone_number: "tollfree"
// }
// });
// $("#id_business_name").rules("add", {maxlength: 60 });
// $("#id_address_line_1").rules("add", {maxlength: 30 });
// $("#id_address_line_2").rules("add", {maxlength: 20 });
// $("#id_city").rules("add", {maxlength: 20 });
// $("#id_primary_contact_name").rules("add", {maxlength: 75 });
// $("#id_business_email_address").rules("add", {maxlength: 200 });
// $("#id_business_website").rules("add", {maxlength: 50 });
// $("#id_social_media_link").rules("add", {maxlength: 200 });
// $("#id_business_description").rules("add", {maxlength: 200 });
// $("#id_products_commadelimited").rules("add", {maxlength: 200 });
// $("#id_keyword_specialties_commadelimited").rules("add", {maxlength: 200 });
// $("#id_areas_served_commadelimited").rules("add", {maxlength: 100 });
// $("#id_professional_associations_commadelimited").rules("add", {maxlength: 200 });
// $("#id_services_commadelimited").rules("add", {maxlength: 200 });
// $("#id_logo_url").rules("add", {maxlength: 136 /* Strip off http:// */ });
// $("#id_photo_url_1").rules("add", {maxlength: 200 });
// $.validator.addMethod("reg_addr", function(value, element) {
// var results = validate_via_regex(value, reg_addr);
// if (results !== true){
// $(element).prop("title","Please provide a properly formatted Address. Invalid characters: " + results.join(""));
// return false;
// }
// return results;
// });
// $.validator.addMethod("tollfree", function(value, element) {
// var results = validate_via_regex(value.replace(/\D/g,''), reg_tollfree);
// console.log("go");
// if (results !== true){
// $(element).prop("title","Toll-free numbers aren't accepted as the primary phone number");
// return false;
// }
// return results;
// });
// $.validator.addMethod("reg_business_name", function(value, element) {
// var results = validate_via_regex(value, reg_business_name);
// if (results !== true){
// $(element).prop("title","Please provide a properly formatted Business Name. Invalid characters: " + results.join(""));
// return false;
// }
// return results;
// });
// $.validator.addMethod("reg_city", function(value, element) {
// var results = validate_via_regex(value, reg_city);
// if (results !== true){
// $(element).prop("title","Please provide a properly formatted City name. Invalid characters: " + results.join(""));
// return false;
// }
// return results;
// });
// $.validator.addMethod("reg_comma", function(value, element) {
// var results = validate_via_regex(value, reg_comma);
// if (results !== true){
// $(element).prop("title","Please provide a properly formatted entry. Invalid characters: " + results.join(""));
// return false;
// }
// return results;
// });
// $.validator.addMethod("reg_desc", function(value, element) {
// var results = validate_via_regex(value, reg_desc);
// if (results !== true){
// $(element).prop("title","Please provide a properly formatted Description. Invalid characters: " + results.join(""));
// return false;
// }
// return results;
// });
// $.validator.addMethod("reg_name", function(value, element) {
// var results = validate_via_regex(value, reg_name);
// if (results !== true){
// $(element).prop("title","Please provide a properly formatted Contact Name. Invalid characters: " + results.join(""));
// return false;
// }
// return results;
// });
// $.validator.addMethod("reg_zip", function(value, element) {
// var results = validate_via_regex(value, reg_zip);
// if (results !== true){
// $(element).prop("title","Please provide a properly formatted ZIP code. Invalid characters: " + results.join(""));
// return false;
// }
// return results;
// });
// };
;

View File

@ -0,0 +1,16 @@
namespace :localeze do
desc "Update and Get new LocalezeCategories"
task :import => :environment do
before = LocalezeCategory.count
categories = LocalezeClient.new.categories
ActiveRecord::Base.transaction do
categories.each do |cat|
category = LocalezeCategory.where(name: cat).first_or_create!
end
if before < LocalezeCategory.count
puts "Imported #{LocalezeCategory.count - before} categories."
end
end
end
end

7
test/fixtures/localeze_categories.yml vendored Normal file
View File

@ -0,0 +1,7 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
one:
name: MyString
two:
name: MyString

View File

@ -0,0 +1,7 @@
require 'test_helper'
class ListEntryControllerTest < ActionController::TestCase
# test "the truth" do
# assert true
# end
end

View File

@ -0,0 +1,4 @@
require 'test_helper'
class ListEntryHelperTest < ActionView::TestCase
end

View File

@ -0,0 +1,7 @@
require 'test_helper'
class LocalezeCategoryTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end

View File

@ -0,0 +1,115 @@
/**
* Select2 Bootstrap CSS 1.0
* Compatible with select2 3.3.2 and bootstrap 2.3.1
* MIT License
*/
.select2-container {
vertical-align: middle;
}
.select2-container.input-mini {
width: 60px;
}
.select2-container.input-small {
width: 90px;
}
.select2-container.input-medium {
width: 150px;
}
.select2-container.input-large {
width: 210px;
}
.select2-container.input-xlarge {
width: 270px;
}
.select2-container.input-xxlarge {
width: 530px;
}
.select2-container.input-default {
width: 220px;
}
.select2-container[class*="span"] {
float: none;
margin-left: 0;
}
.select2-container .select2-choice,
.select2-container-multi .select2-choices {
height: 28px;
line-height: 29px;
border: 1px solid #cccccc;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
background: none;
background-color: white;
filter: none;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}
.select2-container .select2-choice div, .select2-container .select2-choice .select2-arrow,
.select2-container.select2-container-disabled .select2-choice div,
.select2-container.select2-container-disabled .select2-choice .select2-arrow {
border-left: none;
background: none;
filter: none;
}
.control-group.error [class^="select2-choice"] {
border-color: #b94a48;
}
.select2-container-multi .select2-choices .select2-search-field {
height: 28px;
line-height: 27px;
}
.select2-drop.select2-drop-active,
.select2-container-active .select2-choice,
.select2-container-multi.select2-container-active .select2-choices {
border-color: rgba(82, 168, 236, 0.8);
border-color: #ccc\0;
outline: none;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
}
[class^="input-"] .select2-container {
font-size: 14px;
}
.input-prepend [class^="select2-choice"] {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.input-append [class^="select2-choice"] {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.select2-dropdown-open [class^="select2-choice"] {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.select2-dropdown-open.select2-drop-above [class^="select2-choice"] {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
[class^="input-"] .select2-offscreen {
position: absolute;
}
/**
* This stops the quick flash when a native selectbox is shown and
* then replaced by a select2 input when javascript kicks in. This can be
* removed if javascript is not present
*/
select.select2 {
height: 28px;
visibility: hidden;
}

File diff suppressed because one or more lines are too long