watchtower 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +40 -0
- data/app/assets/javascripts/watchtower/application.js +15 -0
- data/app/assets/javascripts/watchtower/contacts.js +11 -0
- data/app/assets/javascripts/watchtower/jquery.jqmodal.js +69 -0
- data/app/assets/stylesheets/watchtower/application.css +13 -0
- data/app/assets/stylesheets/watchtower/bootstrap.css +610 -0
- data/app/assets/stylesheets/watchtower/contacts.css +156 -0
- data/app/controllers/watchtower/application_controller.rb +4 -0
- data/app/controllers/watchtower/contacts_controller.rb +101 -0
- data/app/controllers/watchtower/notes_controller.rb +15 -0
- data/app/controllers/watchtower/tags_controller.rb +11 -0
- data/app/helpers/watchtower/application_helper.rb +4 -0
- data/app/helpers/watchtower/contacts_helper.rb +4 -0
- data/app/models/watchtower/address.rb +17 -0
- data/app/models/watchtower/contact.rb +54 -0
- data/app/models/watchtower/custom_data.rb +4 -0
- data/app/models/watchtower/data.rb +15 -0
- data/app/models/watchtower/email.rb +4 -0
- data/app/models/watchtower/note.rb +13 -0
- data/app/models/watchtower/phone.rb +4 -0
- data/app/models/watchtower/tag.rb +14 -0
- data/app/models/watchtower/tagging.rb +9 -0
- data/app/views/layouts/watchtower/application.html.erb +27 -0
- data/app/views/watchtower/addresses/_address.html.erb +2 -0
- data/app/views/watchtower/contacts/_contact.html.erb +9 -0
- data/app/views/watchtower/contacts/_form.html.erb +33 -0
- data/app/views/watchtower/contacts/edit.html.erb +6 -0
- data/app/views/watchtower/contacts/index.html.erb +23 -0
- data/app/views/watchtower/contacts/new.html.erb +5 -0
- data/app/views/watchtower/contacts/show.html.erb +77 -0
- data/app/views/watchtower/emails/_email.html.erb +1 -0
- data/app/views/watchtower/notes/_note.html.erb +1 -0
- data/app/views/watchtower/phones/_phone.html.erb +1 -0
- data/app/views/watchtower/tags/_tag.html.erb +4 -0
- data/app/views/watchtower/tags/index.html.erb +12 -0
- data/app/views/watchtower/tags/show.html.erb +23 -0
- data/config/routes.rb +10 -0
- data/db/migrate/20120616233432_create_watchtower_contacts.rb +12 -0
- data/db/migrate/20120616235440_create_watchtower_data.rb +13 -0
- data/db/migrate/20120617010925_create_watchtower_addresses.rb +18 -0
- data/db/migrate/20120617055914_create_watchtower_notes.rb +13 -0
- data/db/migrate/20120617073423_create_watchtower_taggings.rb +12 -0
- data/db/migrate/20120617073438_create_watchtower_tags.rb +9 -0
- data/lib/tasks/watchtower_tasks.rake +4 -0
- data/lib/watchtower.rb +4 -0
- data/lib/watchtower/engine.rb +11 -0
- data/lib/watchtower/version.rb +3 -0
- metadata +164 -0
@@ -0,0 +1,156 @@
|
|
1
|
+
/*
|
2
|
+
Place all the styles related to the matching controller here.
|
3
|
+
They will automatically be included in application.css.
|
4
|
+
*/
|
5
|
+
|
6
|
+
body {
|
7
|
+
margin: 15px;
|
8
|
+
margin-top: 55px;
|
9
|
+
line-height: 24px !important;
|
10
|
+
margin-left: 35px;
|
11
|
+
}
|
12
|
+
|
13
|
+
ul.tags {
|
14
|
+
list-style: none;
|
15
|
+
margin-left: 0px;
|
16
|
+
}
|
17
|
+
ul.tags li {
|
18
|
+
display: inline-block;
|
19
|
+
}
|
20
|
+
|
21
|
+
dl {
|
22
|
+
margin-top: 0px;
|
23
|
+
clear: both;
|
24
|
+
}
|
25
|
+
|
26
|
+
dt {
|
27
|
+
font-weight: normal;
|
28
|
+
color: #888;
|
29
|
+
clear: both;
|
30
|
+
display: inline-block;
|
31
|
+
width: 50px;
|
32
|
+
}
|
33
|
+
|
34
|
+
dd {
|
35
|
+
display: inline;
|
36
|
+
clear: right;
|
37
|
+
}
|
38
|
+
|
39
|
+
textarea {
|
40
|
+
height: 100px;
|
41
|
+
width: 600px;
|
42
|
+
}
|
43
|
+
|
44
|
+
.navbar-inner {
|
45
|
+
height: 36px;
|
46
|
+
background: #f0f0f0;
|
47
|
+
padding-left: 20px;
|
48
|
+
}
|
49
|
+
|
50
|
+
.navbar a {
|
51
|
+
color: #333 !important;
|
52
|
+
text-shadow: none;
|
53
|
+
}
|
54
|
+
.navbar .brand {
|
55
|
+
margin-left: 15px;
|
56
|
+
}
|
57
|
+
|
58
|
+
.navbar li.active a {
|
59
|
+
height: 20px;
|
60
|
+
color: #f5f5f5 !important;
|
61
|
+
}
|
62
|
+
|
63
|
+
h1, h3 {
|
64
|
+
margin-top: 20px;
|
65
|
+
margin-bottom: 8px;
|
66
|
+
}
|
67
|
+
h1 {
|
68
|
+
font-size: 25px;
|
69
|
+
}
|
70
|
+
|
71
|
+
h3 {
|
72
|
+
font-weight: 200;
|
73
|
+
clear: left;
|
74
|
+
}
|
75
|
+
|
76
|
+
table {
|
77
|
+
width: 100%;
|
78
|
+
}
|
79
|
+
|
80
|
+
.field {
|
81
|
+
margin-bottom: 10px
|
82
|
+
}
|
83
|
+
|
84
|
+
.field input {
|
85
|
+
margin-left: 15px;
|
86
|
+
}
|
87
|
+
|
88
|
+
.notes {
|
89
|
+
list-style: none;
|
90
|
+
margin: 0;
|
91
|
+
margin-left: 15px;
|
92
|
+
}
|
93
|
+
|
94
|
+
.note {
|
95
|
+
background: #f5f5f5;
|
96
|
+
margin-top: 10px;
|
97
|
+
margin-bottom: 10px;
|
98
|
+
padding: 15px;
|
99
|
+
}
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
.dialog {
|
104
|
+
width: 100px;
|
105
|
+
margin: auto;
|
106
|
+
display: none;
|
107
|
+
|
108
|
+
position: fixed;
|
109
|
+
top: 20%;
|
110
|
+
left: 50%;
|
111
|
+
|
112
|
+
margin-left: -300px;
|
113
|
+
width: 500px;
|
114
|
+
|
115
|
+
background-color: #fff;
|
116
|
+
-webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
|
117
|
+
-moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
|
118
|
+
box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
|
119
|
+
-webkit-background-clip: padding-box;
|
120
|
+
-moz-background-clip: padding-box;
|
121
|
+
background-clip: padding-box;
|
122
|
+
color: #333;
|
123
|
+
border: 1px solid #555;
|
124
|
+
border: 1px solid rgba(0, 0, 0, 0.3);
|
125
|
+
}
|
126
|
+
.dialog h2 {
|
127
|
+
margin: 23px;
|
128
|
+
margin-top: 14px;
|
129
|
+
font-size: 20px;
|
130
|
+
font-weight: 400;
|
131
|
+
}
|
132
|
+
.dialog p { margin: 8px;}
|
133
|
+
.dialog p.dlg_content {
|
134
|
+
min-height: 25px;
|
135
|
+
font-size: 15px;
|
136
|
+
padding-left: 15px;
|
137
|
+
}
|
138
|
+
.dialog p.actions {
|
139
|
+
margin: 0;
|
140
|
+
display: block;
|
141
|
+
float: right;
|
142
|
+
height: 30px;
|
143
|
+
text-align: right;
|
144
|
+
padding: 14px 15px 15px;
|
145
|
+
}
|
146
|
+
/* a { display: inline-block; }
|
147
|
+
a.submit {
|
148
|
+
@include button;
|
149
|
+
text-decoration: none;
|
150
|
+
}*/
|
151
|
+
/* }
|
152
|
+
}*/
|
153
|
+
|
154
|
+
|
155
|
+
.jqmOverlay { background-color: #fff; }
|
156
|
+
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require_dependency "watchtower/application_controller"
|
2
|
+
|
3
|
+
module Watchtower
|
4
|
+
class ContactsController < ApplicationController
|
5
|
+
# GET /contacts
|
6
|
+
# GET /contacts.json
|
7
|
+
def index
|
8
|
+
@contacts = Contact.all
|
9
|
+
|
10
|
+
respond_to do |format|
|
11
|
+
format.html # index.html.erb
|
12
|
+
format.json { render json: @contacts }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# GET /contacts/1
|
17
|
+
# GET /contacts/1.json
|
18
|
+
def show
|
19
|
+
@contact = Contact.find(params[:id])
|
20
|
+
|
21
|
+
respond_to do |format|
|
22
|
+
format.html # show.html.erb
|
23
|
+
format.json { render json: @contact }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# GET /contacts/new
|
28
|
+
# GET /contacts/new.json
|
29
|
+
def new
|
30
|
+
@contact = Contact.new
|
31
|
+
|
32
|
+
respond_to do |format|
|
33
|
+
format.html # new.html.erb
|
34
|
+
format.json { render json: @contact }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# GET /contacts/1/edit
|
39
|
+
def edit
|
40
|
+
@contact = Contact.find(params[:id])
|
41
|
+
end
|
42
|
+
|
43
|
+
# POST /contacts
|
44
|
+
# POST /contacts.json
|
45
|
+
def create
|
46
|
+
@contact = Contact.new(params[:contact])
|
47
|
+
|
48
|
+
respond_to do |format|
|
49
|
+
if @contact.save
|
50
|
+
format.html { redirect_to @contact, notice: 'Contact was successfully created.' }
|
51
|
+
format.json { render json: @contact, status: :created, location: @contact }
|
52
|
+
else
|
53
|
+
format.html { render action: "new" }
|
54
|
+
format.json { render json: @contact.errors, status: :unprocessable_entity }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# PUT /contacts/1
|
60
|
+
# PUT /contacts/1.json
|
61
|
+
def update
|
62
|
+
@contact = Contact.find(params[:id])
|
63
|
+
|
64
|
+
respond_to do |format|
|
65
|
+
if @contact.update_attributes(params[:contact])
|
66
|
+
format.html { redirect_to @contact, notice: 'Contact was successfully updated.' }
|
67
|
+
format.json { head :no_content }
|
68
|
+
else
|
69
|
+
format.html { render action: "edit" }
|
70
|
+
format.json { render json: @contact.errors, status: :unprocessable_entity }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# DELETE /contacts/1
|
76
|
+
# DELETE /contacts/1.json
|
77
|
+
def destroy
|
78
|
+
@contact = Contact.find(params[:id])
|
79
|
+
@contact.destroy
|
80
|
+
|
81
|
+
respond_to do |format|
|
82
|
+
format.html { redirect_to contacts_url }
|
83
|
+
format.json { head :no_content }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def tag
|
88
|
+
@contact = Contact.find(params[:id])
|
89
|
+
|
90
|
+
respond_to do |format|
|
91
|
+
if @contact.tag_with(params[:tag_name]).valid?
|
92
|
+
format.html { redirect_to @contact, notice: 'Contact was successfully tagged.' }
|
93
|
+
format.json { head :no_content }
|
94
|
+
else
|
95
|
+
format.html { render action: "show" }
|
96
|
+
format.json { render json: @contact.errors, status: :unprocessable_entity }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_dependency "watchtower/application_controller"
|
2
|
+
|
3
|
+
module Watchtower
|
4
|
+
class NotesController < ApplicationController
|
5
|
+
def create
|
6
|
+
@contact = Contact.find(params[:contact_id])
|
7
|
+
@note = @contact.notes.build(params[:note])
|
8
|
+
if @note.save
|
9
|
+
redirect_to @contact, notice: "Note added."
|
10
|
+
else
|
11
|
+
redirect_to @contact, notice: "Note could not be added."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Watchtower
|
2
|
+
class Address < ActiveRecord::Base
|
3
|
+
attr_accessible :address_1, :address_2, :address_3, :city, :country, :kind, :name, :postcode, :state
|
4
|
+
|
5
|
+
def kind
|
6
|
+
self[:kind] || "primary"
|
7
|
+
end
|
8
|
+
|
9
|
+
def full_address
|
10
|
+
[:address_1, :address_2, :address_3, :city, :state, :country].compact.join("\n")
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
name
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Watchtower
|
2
|
+
class Contact < ActiveRecord::Base
|
3
|
+
attr_accessible :first_name, :gender, :last_name, :middle_name, :primary_phone, :primary_email
|
4
|
+
|
5
|
+
module DataExtension
|
6
|
+
def add(string, opts={})
|
7
|
+
create(content: string, primary: opts[:primary])
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
has_many :emails, :class_name => "Watchtower::Email", :extend => DataExtension
|
12
|
+
has_many :phones, :class_name => "Watchtower::Phone", :extend => DataExtension
|
13
|
+
has_many :custom_data, :class_name => "Watchtower::CustomData", :extend => DataExtension
|
14
|
+
|
15
|
+
has_many :addresses, :class_name => "Watchtower::Address"
|
16
|
+
|
17
|
+
has_many :notes, :class_name => "Watchtower::Note"
|
18
|
+
has_many :users, :through => :notes
|
19
|
+
|
20
|
+
has_many :taggings, :class_name => "Watchtower::Tagging"
|
21
|
+
has_many :tags, :through => :taggings
|
22
|
+
|
23
|
+
def tag_names
|
24
|
+
tags.map(&:to_s)
|
25
|
+
end
|
26
|
+
|
27
|
+
# FIXME: metaprogramming bad
|
28
|
+
%w(email address phone).each do |type|
|
29
|
+
define_method "primary_#{type}" do
|
30
|
+
self.send(type.pluralize).where(primary: true).first || self.send(type.pluralize).first
|
31
|
+
end
|
32
|
+
|
33
|
+
define_method "primary_#{type}=" do |addr|
|
34
|
+
self.send(type.pluralize).build(content: addr, primary: true)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def full_name
|
39
|
+
[first_name, middle_name, last_name].compact.join(' ')
|
40
|
+
end
|
41
|
+
|
42
|
+
def name
|
43
|
+
full_name
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
full_name
|
48
|
+
end
|
49
|
+
|
50
|
+
def tag_with(tag_name)
|
51
|
+
taggings.create(tag: Tag.find_or_create_by_name(tag_name.try(:downcase)))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Watchtower
|
2
|
+
class Tag < ActiveRecord::Base
|
3
|
+
attr_accessible :name
|
4
|
+
|
5
|
+
has_many :taggings, :class_name => "Watchtower::Tagging"
|
6
|
+
has_many :contacts, :through => :taggings
|
7
|
+
|
8
|
+
validates :name, :presence => true
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
name
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|