Commits

jfinkels  committed d71d754 Merge

Merged from branch newphotoheight.

  • Participants
  • Parent commits 453e774, 8fabddc

Comments (0)

Files changed (7)

File ophot/config.py

 # this part without the BASE_DIR.
 PHOTO_DIR = 'static/photos/'
 
+# The height to which uploaded photos will be scaled so that when they are
+# displayed, they will be of uniform height.
+PHOTO_HEIGHT = 600
+
+# Images will be resized to at most these dimensions (in pixels) and stored as
+# thumbnails for use in the purchase prints page.
+THUMBNAIL_SIZE = (180, 180)
+
 # This is the path to the splash photo. If the user changes the splash photo
 # using the web interface, this photo will be overwritten with the image file
 # which the user uploads.
 # These are the dimensions (in pixels) to which photos uploaded to be the
 # background of the splash page will be resized (if necessary). NOTE: these
 # dimensions should probably be the same size as the <div> element which
-# contains the image! You can see that in the static/style.css file under
+# contains the image! You can see that in the static/style/style.css file under
 # "div#splash".
-SPLASH_PHOTO_WIDTH = 800
-SPLASH_PHOTO_HEIGHT = 535
-
-# Images will be resized to at most these dimensions (in pixels) and stored as
-# thumbnails for use in the purchase prints page.
-THUMBNAIL_SIZE = (180, 180)
-
-# The height to which uploaded photos will be scaled so that when they are
-# displayed, they will be of uniform height.
-PHOTO_HEIGHT = 440
+SPLASH_PHOTO_HEIGHT = PHOTO_HEIGHT + 95
+SPLASH_PHOTO_WIDTH = 1039
 
 # This is the location of the database schema (relative to the directory from
 # which the "reset-db.sh" script is run, which is the top level directory of

File ophot/static/scripts/splash.js

  */
 (function () {
   "use strict";
-  var prevScrollLeft, MAXPOSITION;
+  var prevScrollLeft, MAXPOSITION, BANNER_TOP, BANNER_BOTTOM;
+  /**
+   * The value for the `top` CSS attribute for the `div#banner` element after
+   * a category of photos has been clicked.
+   *
+   * This should be the same as in static/style/style.css.
+   */
+  BANNER_TOP = 560;
+  /**
+   * The value for the `top` CSS attribute for the `div#banner` element after
+   * a category of photos has been clicked.
+   */
+  BANNER_BOTTOM = 657;
+  /**
+   * The maximum number of horizontal pixels beyond which the splash photo will
+   * be completely blacked out when scrolling right through a list of photos.
+   */
   MAXPOSITION = 600;
 
   /** Create the HTML template for purchase information. */
   function fadeOutFadeIn(inSelector) {
     $("#photos-container").fadeOut(400, function() {
       $("#banner").animate(
-        { top : 400 },
+        { top : BANNER_TOP },
         {
           duration: 500,
           complete: function() {
         $(".submenu").hide(0, function() {
           $("#photos-container").fadeOut();
           $("#splash-shadow").fadeOut(400, function() {
-            $("#banner").animate({ top : 400 }, 500);
+            $("#banner").animate({ top : BANNER_TOP }, 500);
           });
         });
       } else {
         fadeOutMany(["#contact-info", "#purchase-info", "#bio"]);
         if ($("#photos-container").is(":hidden")) {
           $("#banner").animate(
-            { top : 497 },
+            { top : BANNER_BOTTOM },
             {
               duration: 500,
               complete: function() {

File ophot/static/style/style.css

   opacity: 0.8;
   padding: 10px;
   position: relative;
-  top: 400px;
+  top: 560px;
   z-index: 6;
 }
 
  */
 .container {
   left: 50%;
-  margin-left: -400px;
-  width: 800px;
+  /**
+   * The following values must be declared in templates/layout.html because
+   * they depend on the application configuration.
+   *
+   * `width` should be the width of the splash photo as specified in the
+   * application configuration.
+   *
+   * `margin-left` should be the negative of one half the width.
+   */
+  /* margin-left: -400px; */
+  /* width: 800px; */
 }
 
 .credentials {
   -moz-box-shadow: 0 0 5px black;
   -webkit-box-shadow: 0 0 5px black;
   box-shadow: 0 0 5px black;
-  height: 450px;
+  /**
+   * The following values must be declared in templates/splash.html because
+   * they depend on the application configuration.
+   *
+   * `height` should be the photo height plus 10 pixels.
+   *
+   * `min-width` should be the width of the splash photo.
+   */
+  /* height: 610px; */
   top: 90px;
-  min-width: 800px;
+  /* min-width: 1039px; */
   z-index: 10;
 }
 
 }
 
 .splash, .splash-shadow {
- height: 535px;
+  /**
+   * The following values must be declared in templates/splash.html because
+   * they depend on the application configuration.
+   *
+   * `height` should be the height of the splash photo.
+   *
+   * `width` should be the width of the splash photo.
+   */
+  /* height: 535px; */
   -moz-border-radius: 10px;
   border-radius: 10px;
-  width: 800px;
+  /* width: 800px; */
 }
 
 .splash-shadow {

File ophot/templates/layout.html

   {% if logged_in %}
   <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style/admin.css') }}" />
   {% endif %}
+  <style type="text/css">
+    /**
+     * The height and width of the splash photo is specified in the application
+     * configuration.
+     */
+    .container {
+      margin-left: -{{ splash_photo_width // 2}}px;
+      width: {{ splash_photo_width }}px;
+    }
+  </style>
   {% endblock %}
 
   {% block scripts %}

File ophot/templates/splash.html

     .photo-cell:first-child {
       padding-left: 0;
     }
+
+    /**
+     * The height and width of the splash photo is specified in the application
+     * configuration.
+     */
+    .photos-container {
+      height: {{ photo_height + 10 }}px;
+      min-width: {{ splash_photo_width }}px;
+    }
+
+    .splash, .splash-shadow {
+      height: {{ splash_photo_height }}px;
+      width: {{ splash_photo_width }}px;
+    }
   </style>
 
   <!-- jscrollpane style (must be included before the javascript) -->

File ophot/tests/test_photos.py

     return set(s).issubset(HEXDIGITS)
 
 
+def photo_filename(static_filename):
+    """Returns the relative filesystem location of the photo with the specified
+    "static filename", the filename used by a HTTP client to request the photo
+    resource.
+
+    """
+    return os.path.join(app.config['BASE_DIR'], static_filename)
+
+
 # TODO override setUp() and tearDown() in this class to just do whatever with
 # temp_photos() does
 class AllPhotosAPITestCase(TestSupport):
         temp = tempfile.NamedTemporaryFile(suffix='.png')
         img.save(temp.name)
         response = self.app.post('/api/photos', data=dict(categoryid=1,
-                                                      photo=temp))
+                                                          photo=temp))
         self.assertEqual(201, response.status_code)
         result = json.loads(response.data)
         self.assertIn('filename', result)
         self.assertEqual('', result['title'])
         self.assertIn('thumbnail', result)
 
+    def test_post(self):
+        """Test for adding a photo which will be resized."""
+        self._login()
+        max_height = app.config['PHOTO_HEIGHT']
+        img = Image.new('RGBA', (2 * max_height, 2 * max_height))
+        temp = tempfile.NamedTemporaryFile(suffix='.png')
+        img.save(temp.name)
+        response = self.app.post('/api/photos', data=dict(categoryid=1,
+                                                          photo=temp))
+        self.assertEqual(201, response.status_code)
+        result = json.loads(response.data)
+        self.assertIn('filename', result)
+        self.assertEqual(1, result['displayposition'])
+        self.assertEqual(1, result['categoryid'])
+        self.assertEqual(1, result['id'])
+        self.assertEqual('', result['title'])
+        self.assertIn('thumbnail', result)
+        new_img = Image.open(photo_filename(result['filename']))
+        self.assertEqual(new_img.size, (max_height, max_height))
+
     def test_add_photo_with_title(self):
         """Test for adding a photo with a title."""
         self._login()
         response = self.app.post('/api/photos', data=dict(categoryid=1,
                                                       photo=temp))
         photo = json.loads(response.data)
-        thumb = Image.open(os.path.join(app.config['BASE_DIR'],
-                                        photo['thumbnail']))
+        thumb = Image.open(photo_filename(photo['thumbnail']))
         self.assertLessEqual(thumb.size[0], app.config['THUMBNAIL_SIZE'][0])
         self.assertLessEqual(thumb.size[1], app.config['THUMBNAIL_SIZE'][1])
 

File ophot/views.py

 
 def render_template(*args, **kw):
     """Delegates to Flask's :func:`flask.render_template` function, but first
-    assigns values to the keyword arguments ``logged_in`` and ``realname``,
-    which are expected by every template.
+    assigns values to the keyword arguments ``logged_in``, ``realname``, and
+    ``splash_photo_width`` which are expected by every template.
+
+    ``logged_in`` is a boolean representing whether the administrator is
+    currently logged in. It specified whether links for editing and managing
+    photos will be shown.
+
+    ``realname`` is the full (human) name of the photographer. It is displayed
+    in parts of the header and footer on each page.
+
+    ``splash_photo_width`` is the width of the background photo on the splash
+    page as specified in the application configuration (see
+    :file:`config.py`). The width of the main ``div`` containing the content of
+    each page depends on the width of the splash photo (so that the content of
+    each page has a consistent width).
 
     """
-    kw['logged_in'] = current_user.is_authenticated()
-    kw['realname'] = app.config['NAME']
+    kw.update(logged_in=current_user.is_authenticated(),
+              realname=app.config['NAME'],
+              splash_photo_width=app.config['SPLASH_PHOTO_WIDTH'])
     return _render_template(*args, **kw)
 
 
     """Shows the splash page as the root."""
     user = json.loads(UserAPI().get().data)
     categories = json.loads(_get_categories().data)['items']
+    splash_height = app.config['SPLASH_PHOTO_HEIGHT']
+    splash_filename = app.config['SPLASH_PHOTO_FILENAME']
+    photo_height = app.config['PHOTO_HEIGHT']
     return render_template('splash.html', categories=categories,
-                           filename=app.config['SPLASH_PHOTO_FILENAME'],
                            photo_padding=user['spacing'], bio=user['bio'],
                            purchase=user['purchase'], contact=user['contact'],
-                           purchase_email=app.config['PURCHASE_EMAIL'])
+                           purchase_email=app.config['PURCHASE_EMAIL'],
+                           filename=splash_filename,
+                           splash_photo_height=splash_height,
+                           photo_height=photo_height)
 
 
 @app.errorhandler(401)