caboose-rets 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/MIT-LICENSE +20 -0
- data/README.md +4 -0
- data/Rakefile +38 -0
- data/app/controllers/caboose_rets/agents_controller.rb +169 -0
- data/app/controllers/caboose_rets/application_controller.rb +6 -0
- data/app/controllers/caboose_rets/commercial_controller.rb +281 -0
- data/app/controllers/caboose_rets/land_controller.rb +69 -0
- data/app/controllers/caboose_rets/open_houses_controller.rb +60 -0
- data/app/controllers/caboose_rets/residential_controller.rb +108 -0
- data/app/helpers/caboose_rets/application_helper.rb +4 -0
- data/app/models/caboose_rets/agent.rb +65 -0
- data/app/models/caboose_rets/commercial_property.rb +214 -0
- data/app/models/caboose_rets/land_property.rb +143 -0
- data/app/models/caboose_rets/media.rb +23 -0
- data/app/models/caboose_rets/multi_family_property.rb +198 -0
- data/app/models/caboose_rets/office.rb +27 -0
- data/app/models/caboose_rets/open_house.rb +19 -0
- data/app/models/caboose_rets/residential_property.rb +236 -0
- data/app/models/caboose_rets/rets_importer.rb +303 -0
- data/app/models/caboose_rets/rets_plugin.rb +26 -0
- data/app/views/caboose_rets/agents/_admin_top_nav.html.erb +7 -0
- data/app/views/caboose_rets/agents/admin_edit.html.erb +28 -0
- data/app/views/caboose_rets/agents/admin_edit_bio.html.erb +31 -0
- data/app/views/caboose_rets/agents/admin_edit_contact_info.html.erb +31 -0
- data/app/views/caboose_rets/agents/admin_edit_mls_info.html.erb +71 -0
- data/app/views/caboose_rets/agents/admin_index.html.erb +48 -0
- data/app/views/caboose_rets/agents/details.html.erb +140 -0
- data/app/views/caboose_rets/agents/index.html.erb +163 -0
- data/app/views/caboose_rets/agents/listings.html.erb +121 -0
- data/app/views/caboose_rets/commercial/admin_edit.html.erb +452 -0
- data/app/views/caboose_rets/commercial/admin_index.html.erb +46 -0
- data/app/views/caboose_rets/commercial/details.html.erb +134 -0
- data/app/views/caboose_rets/commercial/index.html.erb +87 -0
- data/app/views/caboose_rets/open_houses/admin_new.html.erb +31 -0
- data/app/views/caboose_rets/residential/admin_edit.html.erb +250 -0
- data/app/views/caboose_rets/residential/admin_index.html.erb +44 -0
- data/app/views/caboose_rets/residential/details.html.erb +139 -0
- data/app/views/caboose_rets/residential/index.html.erb +102 -0
- data/app/views/caboose_rets/residential/residential_not_exists.html.erb +15 -0
- data/app/views/caboose_rets/residential/test_form.html.erb +4 -0
- data/config/routes.rb +87 -0
- data/lib/caboose-rets.rb +4 -0
- data/lib/caboose_rets/caboose_rets_helper.rb +2 -0
- data/lib/caboose_rets/engine.rb +7 -0
- data/lib/caboose_rets/version.rb +3 -0
- data/lib/tasks/caboose_rets.rake +855 -0
- data/test/caboose_test.rb +7 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/test.log +25 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +15 -0
- metadata +169 -0
@@ -0,0 +1,303 @@
|
|
1
|
+
require 'ruby-rets'
|
2
|
+
require 'httparty'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
# Check for examples:
|
6
|
+
# http://rets.solidearth.com/ClientHome.aspx
|
7
|
+
# https://www.flexmls.com/developers/rets/tutorials/dmql-tutorial/
|
8
|
+
# https://www.flexmls.com/developers/rets/tutorials/how-to-efficiently-replicate-rets-data/
|
9
|
+
|
10
|
+
class CabooseRets::RetsImporter # < ActiveRecord::Base
|
11
|
+
|
12
|
+
@@rets_client = nil
|
13
|
+
@@config = nil
|
14
|
+
@@object_types = {
|
15
|
+
'OpenHouse' => ['OPH'],
|
16
|
+
'Media' => ['GFX'],
|
17
|
+
'Property' => ['COM', 'LND', 'MUL', 'RES'],
|
18
|
+
'Agent' => ['AGT'],
|
19
|
+
'Office' => ['OFF']
|
20
|
+
}
|
21
|
+
@@key_fields = {
|
22
|
+
'OpenHouse' => 'ID',
|
23
|
+
'Media' => 'MEDIA_ID',
|
24
|
+
'Property' => 'MLS_ACCT',
|
25
|
+
'Agent' => 'LA_LA_CODE',
|
26
|
+
'Office' => 'LO_LO_CODE'
|
27
|
+
}
|
28
|
+
@@models = {
|
29
|
+
'OPH' => 'CabooseRets::OpenHouse',
|
30
|
+
'GFX' => 'CabooseRets::Media',
|
31
|
+
'COM' => 'CabooseRets::CommercialProperty',
|
32
|
+
'LND' => 'CabooseRets::LandProperty',
|
33
|
+
'MUL' => 'CabooseRets::MultiFamilyProperty',
|
34
|
+
'RES' => 'CabooseRets::ResidentialProperty',
|
35
|
+
'AGT' => 'CabooseRets::Agent',
|
36
|
+
'OFF' => 'CabooseRets::Office'
|
37
|
+
}
|
38
|
+
@@date_modified_fields = {
|
39
|
+
'OPH' => 'DATE_MODIFIED',
|
40
|
+
'GFX' => 'DATE_MODIFIED',
|
41
|
+
'COM' => 'DATE_MODIFIED',
|
42
|
+
'LND' => 'DATE_MODIFIED',
|
43
|
+
'MUL' => 'DATE_MODIFIED',
|
44
|
+
'RES' => 'DATE_MODIFIED',
|
45
|
+
'AGT' => 'LA_DATE_MODIFIED',
|
46
|
+
'OFF' => 'LO_DATE_MODIFIED'
|
47
|
+
}
|
48
|
+
|
49
|
+
def self.config
|
50
|
+
return @@config
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.get_config
|
54
|
+
@@config = {
|
55
|
+
'url' => nil, # URL to the RETS login
|
56
|
+
'username' => nil,
|
57
|
+
'password' => nil,
|
58
|
+
'limit' => nil, # How many records to limit per request
|
59
|
+
'days_per_batch' => nil, # When performing a large property import, how many days to search on per batch
|
60
|
+
'temp_path' => nil,
|
61
|
+
'log_file' => nil,
|
62
|
+
'media_base_url' => nil
|
63
|
+
}
|
64
|
+
config = YAML::load(File.open("#{Rails.root}/config/rets_importer.yml"))
|
65
|
+
config = config[Rails.env]
|
66
|
+
config.each { |key,val| @@config[key] = val }
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.client
|
70
|
+
self.get_config if @@config.nil? || @@config['url'].nil?
|
71
|
+
|
72
|
+
if (@@rets_client.nil?)
|
73
|
+
@@rets_client = RETS::Client.login(
|
74
|
+
:url => @@config['url'],
|
75
|
+
:username => @@config['username'],
|
76
|
+
:password => @@config['password']
|
77
|
+
)
|
78
|
+
end
|
79
|
+
return @@rets_client
|
80
|
+
end
|
81
|
+
|
82
|
+
#=============================================================================
|
83
|
+
# Main updater
|
84
|
+
#=============================================================================
|
85
|
+
|
86
|
+
def self.update_after(date_modified)
|
87
|
+
self.get_config if @@config.nil? || @@config['url'].nil?
|
88
|
+
|
89
|
+
# Import the data
|
90
|
+
self.import_modified_after(date_modified, 'Agent' , 'AGT')
|
91
|
+
self.import_modified_after(date_modified, 'Office' , 'OFF')
|
92
|
+
self.import_modified_after(date_modified, 'OpenHouse' , 'OPH')
|
93
|
+
self.import_modified_after(date_modified, 'Property' , 'COM')
|
94
|
+
self.import_modified_after(date_modified, 'Property' , 'LND')
|
95
|
+
self.import_modified_after(date_modified, 'Property' , 'MUL')
|
96
|
+
self.import_modified_after(date_modified, 'Property' , 'RES')
|
97
|
+
#self.update_coords(obj)
|
98
|
+
|
99
|
+
# Import the images
|
100
|
+
self.download_agent_images_modified_after(date_modified)
|
101
|
+
self.download_property_images_modified_after(date_modified)
|
102
|
+
end
|
103
|
+
|
104
|
+
#=============================================================================
|
105
|
+
# Data
|
106
|
+
#=============================================================================
|
107
|
+
|
108
|
+
def self.import_modified_after(date_modified, search_type = nil, class_type = nil)
|
109
|
+
self.get_config if @@config.nil? || @@config['url'].nil?
|
110
|
+
|
111
|
+
d = date_modified
|
112
|
+
date_modified_field = @@date_modified_fields[class_type]
|
113
|
+
|
114
|
+
while d.strftime('%FT%T') <= DateTime.now.strftime('%FT%T') do
|
115
|
+
break if d.nil?
|
116
|
+
|
117
|
+
d2 = d.strftime('%FT%T')
|
118
|
+
d2 << "-"
|
119
|
+
d2 << (d+@@config['days_per_batch']).strftime('%FT%T')
|
120
|
+
|
121
|
+
query = "(#{date_modified_field}=#{d2})"
|
122
|
+
self.import(query, search_type, class_type)
|
123
|
+
|
124
|
+
d = d + @@config['days_per_batch']
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.import(query, search_type, class_type)
|
129
|
+
# See how many records we have
|
130
|
+
self.client.search(
|
131
|
+
:search_type => search_type,
|
132
|
+
:class => class_type,
|
133
|
+
:query => query,
|
134
|
+
:count_mode => :only,
|
135
|
+
:timeout => -1,
|
136
|
+
)
|
137
|
+
# Return if no records found
|
138
|
+
if (self.client.rets_data[:code] == "20201")
|
139
|
+
self.log "No #{search_type}:#{class_type} records found for query: #{query}"
|
140
|
+
return
|
141
|
+
else
|
142
|
+
count = self.client.rets_data[:count]
|
143
|
+
self.log "Importing #{count} #{search_type}:#{class_type} record" + (count == 1 ? "" : "s") + "..."
|
144
|
+
end
|
145
|
+
|
146
|
+
count = self.client.rets_data[:count]
|
147
|
+
batch_count = (count.to_f/@@config['limit'].to_f).ceil
|
148
|
+
|
149
|
+
(0...batch_count).each do |i|
|
150
|
+
params = {
|
151
|
+
:search_type => search_type,
|
152
|
+
:class => class_type,
|
153
|
+
:query => query,
|
154
|
+
:limit => @@config['limit'],
|
155
|
+
:offset => @@config['limit'] * i,
|
156
|
+
:timeout => -1
|
157
|
+
}
|
158
|
+
obj = nil
|
159
|
+
self.client.search(params) do |data|
|
160
|
+
m = @@models[class_type].constantize
|
161
|
+
key_field = @@key_fields[search_type]
|
162
|
+
id = data[key_field].to_i
|
163
|
+
obj = m.exists?(id) ? m.find(id) : m.new
|
164
|
+
obj.parse(data)
|
165
|
+
obj.id = id
|
166
|
+
obj.save
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
#=============================================================================
|
172
|
+
# Agent Images
|
173
|
+
#=============================================================================
|
174
|
+
|
175
|
+
def self.download_agent_images_modified_after(date_modified, agent = nil)
|
176
|
+
if agent.nil?
|
177
|
+
CabooseRets::Agent.where('photo_date_modified > ?', date_modified.strftime('%FT%T')).reorder('last_name, first_name').all.each do |a|
|
178
|
+
self.download_agent_images_modified_after(date_modified, a)
|
179
|
+
end
|
180
|
+
return
|
181
|
+
end
|
182
|
+
|
183
|
+
a = agent
|
184
|
+
self.log "Saving image for #{a.first_name} #{a.last_name}..."
|
185
|
+
begin
|
186
|
+
self.client.get_object(:resource => :Agent, :type => :Photo, :location => true, :id => a.la_code) do |headers, content|
|
187
|
+
a.image = URI.parse(headers['location'])
|
188
|
+
a.save
|
189
|
+
end
|
190
|
+
rescue RETS::APIError => err
|
191
|
+
self.log "No image for #{a.first_name} #{a.last_name}."
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
#=============================================================================
|
196
|
+
# Property Images
|
197
|
+
#=============================================================================
|
198
|
+
|
199
|
+
def self.download_property_images_modified_after(date_modified)
|
200
|
+
[CommercialProperty, LandProperty, MultiFamilyProperty, ResidentialProperty].each do |model|
|
201
|
+
model.where("photo_date_modified > ?", date_modified.strftime('%FT%T')).each do |p|
|
202
|
+
self.download_property_images(p)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.download_property_images(p)
|
208
|
+
self.refresh_property_media(p)
|
209
|
+
self.client.get_object(:resource => :Property, :type => :Photo, :location => true, :id => p.id) do |headers, content|
|
210
|
+
|
211
|
+
# Find the associated media record for the image
|
212
|
+
filename = File.basename(headers['location'])
|
213
|
+
m = CabooseRets::Media.where(:mls_acct => p.mls_acct, :file_name => filename).first
|
214
|
+
|
215
|
+
if m.nil?
|
216
|
+
self.log("Can't find media record for #{p.mls_acct} #{filename}.")
|
217
|
+
else
|
218
|
+
m.image = URI.parse(headers['location'])
|
219
|
+
m.save
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def self.refresh_property_media(p)
|
226
|
+
CabooseRets::Media.where(:mls_acct => p.mls_acct, :media_type => 'Photo').destroy_all
|
227
|
+
|
228
|
+
params = {
|
229
|
+
:search_type => 'Media',
|
230
|
+
:class => 'GFX',
|
231
|
+
:query => "(MLS_ACCT=*#{p.id}*),(MEDIA_TYPE=|I)",
|
232
|
+
:timeout => -1
|
233
|
+
}
|
234
|
+
self.client.search(params) do |data|
|
235
|
+
m = CabooseRets::Media.new
|
236
|
+
m.parse(data)
|
237
|
+
m.id = m.media_id
|
238
|
+
m.save
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
#=============================================================================
|
243
|
+
# GPS
|
244
|
+
#=============================================================================
|
245
|
+
|
246
|
+
def self.update_coords(p, type = 'RES')
|
247
|
+
if type == 'RES'
|
248
|
+
self.update_property_coords(ResidentialProperty, 'residential', p)
|
249
|
+
elsif type == 'COM'
|
250
|
+
self.update_property_coords(CommercialProperty, 'commercial', p)
|
251
|
+
elsif type == 'LND'
|
252
|
+
self.update_property_coords(LandProperty, 'land', p)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def self.update_property_coords(property_class, symbolic_name, property = nil)
|
257
|
+
if (property.nil?)
|
258
|
+
if (property_class.where(:latitude => nil).count == 0)
|
259
|
+
self.log "All #{symbolic_name} properties have GPS coordinates."
|
260
|
+
return
|
261
|
+
end
|
262
|
+
property_class.where(:latitude => nil).reorder(:mls_acct).each do |p|
|
263
|
+
self.update_property_coords(property_class, symbolic_name, p)
|
264
|
+
end
|
265
|
+
self.update_property_coords(property_class, symbolic_name, nil)
|
266
|
+
return
|
267
|
+
end
|
268
|
+
p = property
|
269
|
+
|
270
|
+
coords = self.coords_from_address(CGI::escape "#{p.street_num} #{p.street_name}, #{p.city}, #{p.state} #{p.zip}")
|
271
|
+
return if coords.nil? || coords == false
|
272
|
+
|
273
|
+
p.latitude = coords['lat']
|
274
|
+
p.longitude = coords['lng']
|
275
|
+
p.save
|
276
|
+
self.log "Saved #{symbolic_name} property #{p.mls_acct} coords"
|
277
|
+
end
|
278
|
+
|
279
|
+
def self.coords_from_address(address)
|
280
|
+
begin
|
281
|
+
uri = "https://maps.googleapis.com/maps/api/geocode/json?address=#{address}&sensor=false"
|
282
|
+
uri.gsub!(" ", "+")
|
283
|
+
|
284
|
+
resp = HTTParty.get(uri)
|
285
|
+
json = JSON.parse(resp.body)
|
286
|
+
return json['results'][0]['geometry']['location']
|
287
|
+
rescue
|
288
|
+
self.log "Error: #{uri}"
|
289
|
+
sleep(2)
|
290
|
+
return false
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
#=============================================================================
|
295
|
+
# Logging
|
296
|
+
#=============================================================================
|
297
|
+
|
298
|
+
def self.log(msg)
|
299
|
+
puts "[rets_importer] #{msg}"
|
300
|
+
Rails.logger.info("[rets_importer] #{msg}")
|
301
|
+
end
|
302
|
+
|
303
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class AdvantagePlugin < Caboose::CaboosePlugin
|
2
|
+
|
3
|
+
def self.admin_nav(nav, user = nil, page = nil)
|
4
|
+
return nav if user.nil? || !user.is_allowed('properties', 'view')
|
5
|
+
|
6
|
+
item = {
|
7
|
+
'id' => 'rets',
|
8
|
+
'text' => 'RETS',
|
9
|
+
'children' => [],
|
10
|
+
'modal' => true
|
11
|
+
}
|
12
|
+
|
13
|
+
item['children'] << { 'id' => 'agents' , 'href' => '/admin/agents' , 'text' => 'Agents' , 'modal' => false }
|
14
|
+
item['children'] << { 'id' => 'agents' , 'href' => '/admin/offices' , 'text' => 'Offices' , 'modal' => false }
|
15
|
+
item['children'] << { 'id' => 'open-houses' , 'href' => '/admin/open-houses' , 'text' => 'Open Houses' , 'modal' => false }
|
16
|
+
item['children'] << { 'id' => 'residential' , 'href' => '/admin/residential' , 'text' => 'Residential Property' , 'modal' => false }
|
17
|
+
item['children'] << { 'id' => 'commercial' , 'href' => '/admin/commercial' , 'text' => 'Commercial Property' , 'modal' => false }
|
18
|
+
item['children'] << { 'id' => 'commercial' , 'href' => '/admin/multi-family' , 'text' => 'Multi-Family Property' , 'modal' => false }
|
19
|
+
item['children'] << { 'id' => 'land' , 'href' => '/admin/land' , 'text' => 'Land Property' , 'modal' => false }
|
20
|
+
|
21
|
+
nav << item
|
22
|
+
|
23
|
+
return nav
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<div class='top_right_controls'>
|
2
|
+
<input type='button' value='General' onclick="window.location='/admin/agents/<%= @agent.id %>/edit';" />
|
3
|
+
<input type='button' value='Bio' onclick="window.location='/admin/agents/<%= @agent.id %>/edit-bio';" />
|
4
|
+
<input type='button' value='Contact Info' onclick="window.location='/admin/agents/<%= @agent.id %>/edit-contact-info';" />
|
5
|
+
<input type='button' value='MLS Info' onclick="window.location='/admin/agents/<%= @agent.id %>/edit-mls-info';" />
|
6
|
+
</div>
|
7
|
+
<p>Agent: <%= "#{@agent.first_name} #{@agent.last_name}, #{@agent.la_code}" %></p>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<h1>Edit Agent</h1>
|
2
|
+
<%= render :partial => 'agents/admin_top_nav' %>
|
3
|
+
|
4
|
+
<div id='agent_<%= @agent.id %>_hide' ></div>
|
5
|
+
<div id='agent_<%= @agent.id %>_assistant_to' ></div>
|
6
|
+
|
7
|
+
<p style='clear: both;'><input type='button' value='< Back' onclick="window.location='/admin/agents';" /></p>
|
8
|
+
|
9
|
+
<% content_for :caboose_js do %>
|
10
|
+
<%= javascript_include_tag "caboose/model/all" %>
|
11
|
+
<script type='text/javascript'>
|
12
|
+
$(document).ready(function() {
|
13
|
+
m = new ModelBinder({
|
14
|
+
name: 'Agent',
|
15
|
+
id: <%= @agent.id %>,
|
16
|
+
update_url: '/admin/agents/<%= @agent.id %>',
|
17
|
+
authenticity_token: '<%= form_authenticity_token %>',
|
18
|
+
attributes: [
|
19
|
+
{ name: 'hide' , nice_name: 'Hide from website' , type: 'checkbox' , value: <%= raw @agent.hide %>, width: 400 },
|
20
|
+
{ name: 'assistant_to' , nice_name: 'Assistant To' , type: 'select' , value: <%= raw Caboose.json(@agent.assistant_to) %>, width: 400, text: <%= raw Caboose.json(@boss ? "#{@boss.first_name} #{@boss.last_name}" : 'empty') %>, options_url: '/admin/agents/assistant-to-options', empty_text: 'Not an assistant' }
|
21
|
+
]
|
22
|
+
});
|
23
|
+
});
|
24
|
+
$(window).load(function() {
|
25
|
+
var modal = new CabooseModal(800);
|
26
|
+
});
|
27
|
+
</script>
|
28
|
+
<% end %>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<h1>Edit Agent</h1>
|
2
|
+
<%= render :partial => 'agents/admin_top_nav' %>
|
3
|
+
|
4
|
+
<div id='agent_<%= @agent.id %>_bio'></div>
|
5
|
+
|
6
|
+
<p style='clear: both;'><input type='button' value='< Back' onclick="window.location='/admin/agents';" /></p>
|
7
|
+
|
8
|
+
<% content_for :caboose_js do %>
|
9
|
+
<%= javascript_include_tag "caboose/model/all" %>
|
10
|
+
<script type='text/javascript'>
|
11
|
+
$(document).ready(function() {
|
12
|
+
m = new ModelBinder({
|
13
|
+
name: 'Agent',
|
14
|
+
id: <%= @agent.id %>,
|
15
|
+
update_url: '/admin/agents/<%= @agent.id %>',
|
16
|
+
authenticity_token: '<%= form_authenticity_token %>',
|
17
|
+
attributes: [{
|
18
|
+
name: 'bio',
|
19
|
+
nice_name: 'Bio',
|
20
|
+
type: 'textarea',
|
21
|
+
value: <%= raw Caboose.json(@agent.bio) %>,
|
22
|
+
width: 600,
|
23
|
+
height: 250
|
24
|
+
}]
|
25
|
+
});
|
26
|
+
});
|
27
|
+
$(window).load(function() {
|
28
|
+
var modal = new CabooseModal(800);
|
29
|
+
});
|
30
|
+
</script>
|
31
|
+
<% end %>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<h1>Edit Agent</h1>
|
2
|
+
<%= render :partial => 'agents/admin_top_nav' %>
|
3
|
+
|
4
|
+
<div id='agent_<%= @agent.id %>_contact_info' ></div>
|
5
|
+
|
6
|
+
<p style='clear: both;'><input type='button' value='< Back' onclick="window.location='/admin/agents';" /></p>
|
7
|
+
|
8
|
+
<% content_for :caboose_js do %>
|
9
|
+
<%= javascript_include_tag "caboose/model/all" %>
|
10
|
+
<script type='text/javascript'>
|
11
|
+
$(document).ready(function() {
|
12
|
+
m = new ModelBinder({
|
13
|
+
name: 'Agent',
|
14
|
+
id: <%= @agent.id %>,
|
15
|
+
update_url: '/admin/agents/<%= @agent.id %>',
|
16
|
+
authenticity_token: '<%= form_authenticity_token %>',
|
17
|
+
attributes: [{
|
18
|
+
name: 'contact_info',
|
19
|
+
nice_name: 'Contact Info',
|
20
|
+
type: 'textarea',
|
21
|
+
value: <%= raw Caboose.json(@agent.contact_info) %>,
|
22
|
+
width: 750,
|
23
|
+
height: 250
|
24
|
+
}]
|
25
|
+
});
|
26
|
+
});
|
27
|
+
$(window).load(function() {
|
28
|
+
var modal = new CabooseModal(800);
|
29
|
+
});
|
30
|
+
</script>
|
31
|
+
<% end %>
|
@@ -0,0 +1,71 @@
|
|
1
|
+
<h1>Edit Agent</h1>
|
2
|
+
<%= render :partial => 'agents/admin_top_nav' %>
|
3
|
+
|
4
|
+
<p>
|
5
|
+
<input type='button' value='< Back' onclick="window.location='/admin/agents';" />
|
6
|
+
<input type='button' value='Refresh from MLS' onclick="refresh_agent_from_mls(<%= @agent.id %>);" />
|
7
|
+
</p>
|
8
|
+
<div id='message'><%= raw flash[:message] ? flash[:message] : "" %></div>
|
9
|
+
|
10
|
+
<table class='data'>
|
11
|
+
<tr><td>beeper_phone </td><td><%= @agent.beeper_phone %></td></tr>
|
12
|
+
<tr><td>car_phone </td><td><%= @agent.car_phone %></td></tr>
|
13
|
+
<tr><td>date_created </td><td><%= @agent.date_created %></td></tr>
|
14
|
+
<tr><td>date_modified </td><td><%= @agent.date_modified %></td></tr>
|
15
|
+
<tr><td>defaultemail </td><td><%= @agent.defaultemail %></td></tr>
|
16
|
+
<tr><td>fax_phone </td><td><%= @agent.fax_phone %></td></tr>
|
17
|
+
<tr><td>first_name </td><td><%= @agent.first_name %></td></tr>
|
18
|
+
<tr><td>home_phone </td><td><%= @agent.home_phone %></td></tr>
|
19
|
+
<tr><td>la_code </td><td><%= @agent.la_code %></td></tr>
|
20
|
+
<tr><td>last_name </td><td><%= @agent.last_name %></td></tr>
|
21
|
+
<tr><td>lo_code </td><td><%= @agent.lo_code %></td></tr>
|
22
|
+
<tr><td>mail_addr1 </td><td><%= @agent.mail_addr1 %></td></tr>
|
23
|
+
<tr><td>mail_addr2 </td><td><%= @agent.mail_addr2 %></td></tr>
|
24
|
+
<tr><td>mail_city </td><td><%= @agent.mail_city %></td></tr>
|
25
|
+
<tr><td>mail_state </td><td><%= @agent.mail_state %></td></tr>
|
26
|
+
<tr><td>mail_zip </td><td><%= @agent.mail_zip %></td></tr>
|
27
|
+
<tr><td>member_email </td><td><%= @agent.member_email %></td></tr>
|
28
|
+
<tr><td>member_page </td><td><%= @agent.member_page %></td></tr>
|
29
|
+
<tr><td>member_status </td><td><%= @agent.member_status %></td></tr>
|
30
|
+
<tr><td>nrds_id </td><td><%= @agent.nrds_id %></td></tr>
|
31
|
+
<tr><td>office_phone </td><td><%= @agent.office_phone %></td></tr>
|
32
|
+
<tr><td>other_phone </td><td><%= @agent.other_phone %></td></tr>
|
33
|
+
<tr><td>phone_change_date </td><td><%= @agent.phone_change_date %></td></tr>
|
34
|
+
<tr><td>phone_direct_office </td><td><%= @agent.phone_direct_office %></td></tr>
|
35
|
+
<tr><td>phone_home_fax </td><td><%= @agent.phone_home_fax %></td></tr>
|
36
|
+
<tr><td>phone_pager </td><td><%= @agent.phone_pager %></td></tr>
|
37
|
+
<tr><td>phone_second_home </td><td><%= @agent.phone_second_home %></td></tr>
|
38
|
+
<tr><td>phone_toll_free </td><td><%= @agent.phone_toll_free %></td></tr>
|
39
|
+
<tr><td>phone_voice_mail </td><td><%= @agent.phone_voice_mail %></td></tr>
|
40
|
+
<tr><td>phone_voice_pager </td><td><%= @agent.phone_voice_pager %></td></tr>
|
41
|
+
<tr><td>photo_count </td><td><%= @agent.photo_count %></td></tr>
|
42
|
+
<tr><td>photo_date_modified </td><td><%= @agent.photo_date_modified %></td></tr>
|
43
|
+
</table>
|
44
|
+
|
45
|
+
<p><input type='button' value='< Back' onclick="window.location='/admin/agents';" /></p>
|
46
|
+
|
47
|
+
<% content_for :caboose_js do %>
|
48
|
+
<%= javascript_include_tag "caboose/model/all" %>
|
49
|
+
<script type='text/javascript'>
|
50
|
+
|
51
|
+
function refresh_agent_from_mls(agent_id)
|
52
|
+
{
|
53
|
+
//modal.autosize("<p class='loading'>Refreshing agent info from MLS...</p>");
|
54
|
+
$.ajax({
|
55
|
+
url: '/admin/agents/' + agent_id + '/refresh',
|
56
|
+
success: function(resp) {
|
57
|
+
if (resp.error)
|
58
|
+
modal.autosize("<p class='note error'>" + resp.error + "</p>");
|
59
|
+
if (resp.reload)
|
60
|
+
location.reload();
|
61
|
+
}
|
62
|
+
});
|
63
|
+
}
|
64
|
+
|
65
|
+
var modal = false;
|
66
|
+
$(window).load(function() {
|
67
|
+
modal = new CabooseModal(800);
|
68
|
+
});
|
69
|
+
|
70
|
+
</script>
|
71
|
+
<% end %>
|