1#!/usr/bin/python2.5
2
3# Copyright (C) 2010 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may not
6# use this file except in compliance with the License. You may obtain a copy of
7# the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations under
15# the License.
16
17"""
18Defines Django forms for inserting/updating/viewing contact data
19to/from SampleSyncAdapter datastore.
20"""
21
22import cgi
23import datetime
24import os
25
26from google.appengine.ext import db
27from google.appengine.ext import webapp
28from google.appengine.ext.webapp import template
29from google.appengine.ext.db import djangoforms
30from model import datastore
31from google.appengine.api import images
32
33import wsgiref.handlers
34
35class BaseRequestHandler(webapp.RequestHandler):
36    """
37    Base class for our page-based request handlers that contains
38    some helper functions we use in most pages.
39    """
40
41    """
42    Return a form (potentially partially filled-in) to
43    the user.
44    """
45    def send_form(self, title, action, contactId, handle, content_obj):
46        if (contactId >= 0):
47            idInfo = '<input type="hidden" name="_id" value="%s">'
48        else:
49            idInfo = ''
50
51        template_values = {
52                'title': title,
53                'header': title,
54                'action': action,
55                'contactId': contactId,
56                'handle': handle,
57                'has_contactId': (contactId >= 0),
58                'has_handle': (handle != None),
59                'form_data_rows': str(content_obj)
60                }
61
62        path = os.path.join(os.path.dirname(__file__), 'templates', 'simple_form.html')
63        self.response.out.write(template.render(path, template_values))
64
65class ContactForm(djangoforms.ModelForm):
66    """Represents django form for entering contact info."""
67
68    class Meta:
69        model = datastore.Contact
70
71
72class ContactInsertPage(BaseRequestHandler):
73    """
74    Processes requests to add a new contact. GET presents an empty
75    contact form for the user to fill in.  POST saves the new contact
76    with the POSTed information.
77    """
78
79    def get(self):
80        self.send_form('Add Contact', '/add_contact', -1, None, ContactForm())
81
82    def post(self):
83        data = ContactForm(data=self.request.POST)
84        if data.is_valid():
85            # Save the data, and redirect to the view page
86            entity = data.save(commit=False)
87            entity.put()
88            self.redirect('/')
89        else:
90            # Reprint the form
91            self.send_form('Add Contact', '/add_contact', -1, None, data)
92
93
94class ContactEditPage(BaseRequestHandler):
95    """
96    Process requests to edit a contact's information.  GET presents a form
97    with the current contact information filled in. POST saves new information
98    into the contact record.
99    """
100
101    def get(self):
102        id = int(self.request.get('id'))
103        contact = datastore.Contact.get(db.Key.from_path('Contact', id))
104        self.send_form('Edit Contact', '/edit_contact', id, contact.handle,
105                       ContactForm(instance=contact))
106
107    def post(self):
108        id = int(self.request.get('id'))
109        contact = datastore.Contact.get(db.Key.from_path('Contact', id))
110        data = ContactForm(data=self.request.POST, instance=contact)
111        if data.is_valid():
112            # Save the data, and redirect to the view page
113            entity = data.save(commit=False)
114            entity.updated = datetime.datetime.utcnow()
115            entity.put()
116            self.redirect('/')
117        else:
118            # Reprint the form
119            self.send_form('Edit Contact', '/edit_contact', id, contact.handle, data)
120
121class ContactDeletePage(BaseRequestHandler):
122    """Processes delete contact request."""
123
124    def get(self):
125        id = int(self.request.get('id'))
126        contact = datastore.Contact.get(db.Key.from_path('Contact', id))
127        contact.deleted = True
128        contact.updated = datetime.datetime.utcnow()
129        contact.put()
130
131        self.redirect('/')
132
133class AvatarEditPage(webapp.RequestHandler):
134    """
135    Processes requests to edit contact's avatar. GET is used to fetch
136    a page that displays the contact's current avatar and allows the user
137    to specify a file containing a new avatar image.  POST is used to
138    submit the form which will change the contact's avatar.
139    """
140
141    def get(self):
142        id = int(self.request.get('id'))
143        contact = datastore.Contact.get(db.Key.from_path('Contact', id))
144        template_values = {
145                'avatar': contact.avatar,
146                'contactId': id
147                }
148
149        path = os.path.join(os.path.dirname(__file__), 'templates', 'edit_avatar.html')
150        self.response.out.write(template.render(path, template_values))
151
152    def post(self):
153        id = int(self.request.get('id'))
154        contact = datastore.Contact.get(db.Key.from_path('Contact', id))
155        #avatar = images.resize(self.request.get("avatar"), 128, 128)
156        avatar = self.request.get("avatar")
157        contact.avatar = db.Blob(avatar)
158        contact.updated = datetime.datetime.utcnow()
159        contact.put()
160        self.redirect('/')
161
162class AvatarViewPage(BaseRequestHandler):
163    """
164    Processes request to view contact's avatar. This is different from
165    the GET AvatarEditPage request in that this doesn't return a page -
166    it just returns the raw image itself.
167    """
168
169    def get(self):
170        id = int(self.request.get('id'))
171        contact = datastore.Contact.get(db.Key.from_path('Contact', id))
172        if (contact.avatar):
173            self.response.headers['Content-Type'] = "image/png"
174            self.response.out.write(contact.avatar)
175        else:
176            self.redirect(self.request.host_url + '/static/img/default_avatar.gif')
177
178class ContactsListPage(webapp.RequestHandler):
179    """
180    Display a page that lists all the contacts associated with
181    the specifies user account.
182    """
183
184    def get(self):
185        contacts = datastore.Contact.all()
186        template_values = {
187                'contacts': contacts,
188                'username': 'user'
189                }
190
191        path = os.path.join(os.path.dirname(__file__), 'templates', 'contacts.html')
192        self.response.out.write(template.render(path, template_values))
193
194
195def main():
196    application = webapp.WSGIApplication(
197        [('/', ContactsListPage),
198         ('/add_contact', ContactInsertPage),
199         ('/edit_contact', ContactEditPage),
200         ('/delete_contact', ContactDeletePage),
201         ('/avatar', AvatarViewPage),
202         ('/edit_avatar', AvatarEditPage)
203        ],
204        debug=True)
205    wsgiref.handlers.CGIHandler().run(application)
206
207if __name__ == '__main__':
208  main()