Browse Source

Incoming import

Innocenty Enikeew 10 years ago
parent
commit
39e7478aa6
4 changed files with 87 additions and 45 deletions
  1. 12 1
      assets/site.css
  2. 25 5
      assets/site.js
  3. 7 3
      incoming.html
  4. 43 36
      photo-store.lisp

+ 12 - 1
assets/site.css

@@ -375,7 +375,9 @@ img.img--with_border {
   width: 171px;
 /*  line-height: 0; */
 }
-
+.demo-gallery figure {
+  font-size: 14px;
+}
 
 
 a.demo-gallery__img--main {
@@ -537,3 +539,12 @@ margin: 0 1px 1px 0;
     width: 109px;
   }
 }
+
+div.incoming-album label {
+    width: 60px;
+    display: inline-block;
+}
+
+div.incoming-album input[type='text'] {
+    width: 400px;
+}

+ 25 - 5
assets/site.js

@@ -11,14 +11,34 @@ function setAlbums(albums) {
     });
 }
 
-function setIncoming(albums) {
-    var dAlbums = document.getElementById('albums');
-    dAlbums.innerHTML = '';
+function setIncoming(albums, parent) {
+    parent.innerHTML = '';
     Array.prototype.forEach.call(albums, function(alb, i){
-        var a = addAlbumDom(dAlbums, alb);
-        a.addEventListener('click', function() {
+        var div = appendElement(parent, 'div', null, 'incoming-album');
+        var a = addAlbumDom(div, alb);
+        a.addEventListener('click', function(e) {
+            e.preventDefault();
             startGallery(alb.photos);
         });
+        var form = appendElement(div, 'form', null, null, '<div><p><label>Title</label><input type="text"/></p><p><label>Path</label><input type="text"/></p><p><input type="submit" value="Import"/></p>');
+        form[0].value = alb.title;
+        form[1].value = alb.dest;
+        form.addEventListener('submit', function (e) {
+            e.preventDefault();
+            form[2].disabled = true;
+
+            var paths = Array.prototype.map.call(alb.photos, function(p) {return p.path});
+            var data = JSON.stringify({name: form[0].value,
+                                       dest: form[1].value,
+                                       paths: paths});
+            jsonPOST('/api/incoming/import/', data, function(resp) {
+                alert('Added album ' + resp.id);
+                div.innerHTML = '';
+            }, function(err, req) {
+                alert(err);
+                form[2].disabled = false;
+            });
+        });
     });
 }
 

+ 7 - 3
incoming.html

@@ -42,8 +42,7 @@
     </div>
 
     <div class="section">
-	  <div class="row">
-        <div id="albums" class="demo-gallery"></div>
+	  <div class="row" id="albums">
       </div>
     </div>
 
@@ -88,8 +87,13 @@
 
     <script type="text/javascript">
       jsonGET('/api/incoming/', function(data) {
+          var parent = document.getElementById('albums');
           if (data) 
-              setIncoming(data);
+          {
+              setIncoming(data, parent);
+          } else {
+              appendElement(parent,'h3', null, null, 'No incoming photos');
+          }
       });
     </script>
   </body>

+ 43 - 36
photo-store.lisp

@@ -51,18 +51,20 @@
 (defun db-load-album (album-id)
   (with-db (db)
     (multiple-value-bind (name cover-id)
-        (sqlite:execute-one-row-m-v db "select name, cover_id from albums where id = ?" album-id)
-      (let ((photos (iter (for (id path title w h)
-                               in-sqlite-query "select p.id, p.path, ap.description, p.width, p.height from photos p inner join album_photos ap on ap.photo_id = p.id where ap.album_id = ? order by ap.idx"
-                               on-database db
-                               with-parameters (album-id))
-                          (collect (list (cons :id id)
-                                         (cons :src (concatenate 'string *photo-storage-url* path))
-                                         (cons :title title)
-                                         (cons :w w) (cons :h h))))))
-        (list (cons :title name)
-              (cons :cover (find cover-id photos :key (agetter :id)))
-              (cons :photos photos))))))
+        (sqlite:execute-one-row-m-v db "select id, name, cover_id from albums where id = ?" album-id)
+      (when name
+        (let ((photos (iter (for (id path title w h)
+                                 in-sqlite-query "select p.id, p.path, ap.description, p.width, p.height from photos p inner join album_photos ap on ap.photo_id = p.id where ap.album_id = ? order by ap.idx"
+                                 on-database db
+                                 with-parameters (album-id))
+                            (collect (list (cons :id id)
+                                           (cons :src (concatenate 'string *photo-storage-url* path))
+                                           (cons :title title)
+                                           (cons :w w) (cons :h h))))))
+          (list (cons :id album-id)
+                (cons :title name)
+                (cons :cover (find cover-id photos :key (agetter :id)))
+                (cons :photos photos)))))))
 
 (defun db-load-albums ()
   (with-db (db)
@@ -92,7 +94,7 @@
     (local-time:format-timestring nil from :format format)))
 
 (defun middle (seq)
-  (elt seq (/ (length seq) 2)))
+  (elt seq (floor (length seq) 2)))
 
 (defun imagep (path)
   (equal (string-downcase (pathname-type path)) "jpg"))
@@ -100,18 +102,25 @@
 (defun directory-images (directory)
   (remove-if-not 'imagep (uiop:directory-files directory)))
 
+(defun photo-item (info)
+  `((:src . ,(map-path (aget :path info)))
+    (:path . ,(namestring (aget :path info)))
+    (:title . ,(aget :name info))
+    (:w . ,(first (aget :dim info)))
+    (:h . ,(second (aget :dim info)))))
+
 (defun load-album (directory)
   (let ((photos (mapcar 'load-photo-info (directory-images directory))))
     (when photos
-      (list (cons :title (guess-album-title directory photos))
-            (cons :path directory)
-            (cons :cover (middle photos))
-            (cons :photos photos)))))
+      `((:title . ,(guess-album-title directory photos))
+        (:cover . ,(photo-item (middle photos)))
+        (:dest . ,(guess-album-path directory photos))
+        (:photos . ,(mapcar 'photo-item photos))))))
 
-(defun load-albums-from-dir (directory)
-  (remove-if #'null (list* (load-album directory)
-                           (loop for subdir in (uiop:subdirectories directory)
-                              append (load-albums-from-dir subdir)))))
+(defun fs-load-albums (directory)
+  (delete nil (list* (load-album directory)
+                     (loop for subdir in (uiop:subdirectories directory)
+                        append (fs-load-albums subdir)))))
 
 (defvar *path-url-mapping* nil "alist of path-2-url mapping")
 (defun map-path (path)
@@ -120,20 +129,6 @@
      when rel-path do (return (concatenate 'string base-url (namestring rel-path)))
      finally (error "Can't map path ~S" path)))
 
-(defun photo-item (info &optional incoming)
-  `((:src . ,(map-path (aget :path info)))
-    ,@(when incoming (list (cons :path (namestring (aget :path info)))))
-    (:w . ,(first (aget :dim info)))
-    (:h . ,(second (aget :dim info)))))
-
-(defun album-item (album &optional incoming)
-  `((:title . ,(aget :title album))
-    (:cover . ,(photo-item (aget :cover album)))
-    ,@(when incoming (list (cons :path (namestring (aget :path album)))
-                           (cons :dest (guess-album-path (aget :path album)
-                                                         (aget :photos album)))))
-    (:photos . ,(mapcar #'(lambda (p) (photo-item p incoming)) (aget :photos album)))))
-
 (defun other-images (directory images)
   (remove-if #'(lambda (img) (member img images :test #'equal))
              (directory-images directory)))
@@ -204,7 +199,19 @@
 (defvar *incoming-path* nil "Path for incoming photos")
 (restas:define-route api/incoming ("api/incoming/"
                                    :content-type "application/json")
-  (json (mapcar #'(lambda (a) (album-item a t)) (load-albums-from-dir *incoming-path*))))
+  (json (fs-load-albums *incoming-path*)))
+
+(restas:define-route api/incoming-import ("api/incoming/import/"
+                                          :method :post
+                                          :content-type "application/json")
+  (let* ((album (json:decode-json-from-string (hunchentoot:raw-post-data :external-format :utf-8)))
+         (name (aget :name album))
+         (dest (aget :dest album))
+         (paths (aget :paths album)))
+    (if (uiop:relative-pathname-p dest)
+        (let ((new-id (import-album name (uiop:merge-pathnames* dest *photo-storage-path*) paths)))
+          (json (db-load-album new-id)))
+        400)))
 
 (restas:define-route api/albums ("api/albums/"
                                  :content-type "application/json")