watchtower 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +3 -0
  3. data/Rakefile +40 -0
  4. data/app/assets/javascripts/watchtower/application.js +15 -0
  5. data/app/assets/javascripts/watchtower/contacts.js +11 -0
  6. data/app/assets/javascripts/watchtower/jquery.jqmodal.js +69 -0
  7. data/app/assets/stylesheets/watchtower/application.css +13 -0
  8. data/app/assets/stylesheets/watchtower/bootstrap.css +610 -0
  9. data/app/assets/stylesheets/watchtower/contacts.css +156 -0
  10. data/app/controllers/watchtower/application_controller.rb +4 -0
  11. data/app/controllers/watchtower/contacts_controller.rb +101 -0
  12. data/app/controllers/watchtower/notes_controller.rb +15 -0
  13. data/app/controllers/watchtower/tags_controller.rb +11 -0
  14. data/app/helpers/watchtower/application_helper.rb +4 -0
  15. data/app/helpers/watchtower/contacts_helper.rb +4 -0
  16. data/app/models/watchtower/address.rb +17 -0
  17. data/app/models/watchtower/contact.rb +54 -0
  18. data/app/models/watchtower/custom_data.rb +4 -0
  19. data/app/models/watchtower/data.rb +15 -0
  20. data/app/models/watchtower/email.rb +4 -0
  21. data/app/models/watchtower/note.rb +13 -0
  22. data/app/models/watchtower/phone.rb +4 -0
  23. data/app/models/watchtower/tag.rb +14 -0
  24. data/app/models/watchtower/tagging.rb +9 -0
  25. data/app/views/layouts/watchtower/application.html.erb +27 -0
  26. data/app/views/watchtower/addresses/_address.html.erb +2 -0
  27. data/app/views/watchtower/contacts/_contact.html.erb +9 -0
  28. data/app/views/watchtower/contacts/_form.html.erb +33 -0
  29. data/app/views/watchtower/contacts/edit.html.erb +6 -0
  30. data/app/views/watchtower/contacts/index.html.erb +23 -0
  31. data/app/views/watchtower/contacts/new.html.erb +5 -0
  32. data/app/views/watchtower/contacts/show.html.erb +77 -0
  33. data/app/views/watchtower/emails/_email.html.erb +1 -0
  34. data/app/views/watchtower/notes/_note.html.erb +1 -0
  35. data/app/views/watchtower/phones/_phone.html.erb +1 -0
  36. data/app/views/watchtower/tags/_tag.html.erb +4 -0
  37. data/app/views/watchtower/tags/index.html.erb +12 -0
  38. data/app/views/watchtower/tags/show.html.erb +23 -0
  39. data/config/routes.rb +10 -0
  40. data/db/migrate/20120616233432_create_watchtower_contacts.rb +12 -0
  41. data/db/migrate/20120616235440_create_watchtower_data.rb +13 -0
  42. data/db/migrate/20120617010925_create_watchtower_addresses.rb +18 -0
  43. data/db/migrate/20120617055914_create_watchtower_notes.rb +13 -0
  44. data/db/migrate/20120617073423_create_watchtower_taggings.rb +12 -0
  45. data/db/migrate/20120617073438_create_watchtower_tags.rb +9 -0
  46. data/lib/tasks/watchtower_tasks.rake +4 -0
  47. data/lib/watchtower.rb +4 -0
  48. data/lib/watchtower/engine.rb +11 -0
  49. data/lib/watchtower/version.rb +3 -0
  50. 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,4 @@
1
+ module Watchtower
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -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,11 @@
1
+ module Watchtower
2
+ class TagsController < ApplicationController
3
+ def index
4
+ @tags = Tag.all
5
+ end
6
+
7
+ def show
8
+ @tag = Tag.find(params[:id])
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ module Watchtower
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Watchtower
2
+ module ContactsHelper
3
+ end
4
+ 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,4 @@
1
+ module Watchtower
2
+ class CustomData < Watchtower::Data
3
+ end
4
+ end
@@ -0,0 +1,15 @@
1
+ module Watchtower
2
+ class Data < ActiveRecord::Base
3
+ attr_accessible :content, :name, :primary
4
+
5
+ belongs_to :contact, :class_name => "Watchtower::Contact"
6
+
7
+ def name
8
+ self[:name] || "other"
9
+ end
10
+
11
+ def to_s
12
+ content
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ module Watchtower
2
+ class Email < Watchtower::Data
3
+ end
4
+ end
@@ -0,0 +1,13 @@
1
+ module Watchtower
2
+ class Note < ActiveRecord::Base
3
+ belongs_to :user, :class_name => Watchtower.user_class
4
+ belongs_to :contact
5
+ attr_accessible :content
6
+
7
+ validates :content, :presence => true
8
+
9
+ def to_s
10
+ content
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ module Watchtower
2
+ class Phone < Watchtower::Data
3
+ end
4
+ 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
@@ -0,0 +1,9 @@
1
+ module Watchtower
2
+ class Tagging < ActiveRecord::Base
3
+ belongs_to :contact
4
+ belongs_to :tag
5
+ attr_accessible :tag
6
+
7
+ validates :contact_id, :uniqueness => { :scope => :tag_id }
8
+ end
9
+ end