蔵書管理対応、coffescrip対応
authorOHASHI, Norikazu <katz@neko-mori.sakura.ne.jp>
Tue, 30 Apr 2019 12:16:00 +0000 (21:16 +0900)
committerOHASHI, Norikazu <katz@neko-mori.sakura.ne.jp>
Tue, 30 Apr 2019 12:16:00 +0000 (21:16 +0900)
sinatra/app/controllers/web_gui.rb
sinatra/app/models/books_db.rb
sinatra/app/views/coffee/book_regist.haml [new file with mode: 0644]
sinatra/app/views/coffee/check_form.coffee [new file with mode: 0644]
sinatra/app/views/layout.haml
sinatra/app/views/login.haml
sinatra/app/views/scss/style.scss
sinatra/app/views/signup.haml
sinatra/app/views/user_edit.haml
sinatra/app/views/user_home.haml
sinatra/public/scripts/default.js [deleted file]

index e46c8f1..80ea3bf 100644 (file)
@@ -9,6 +9,9 @@ require 'haml'
 # ユーザアクセス用モデル
 require_relative '../models/users_db'
 
+# 蔵書管理用モデル
+require_relative '../models/books_db'
+
 # 書籍管理サーバ WebGUI Controller
 class WebGui < Sinatra::Base
 
@@ -46,7 +49,12 @@ class WebGui < Sinatra::Base
   get '/css/style.css' do
     scss :'scss/style'
   end
-  
+
+  # javaScript
+  get '/scripts/check_form.js' do
+    coffee :'coffee/check_form'
+  end
+
   # メインページ
   get '/' do
     goPage :main
@@ -114,7 +122,9 @@ class WebGui < Sinatra::Base
     @id = id
     @username = user.full_name
     @is_addmin = user.isAddmin
-    @newest_list = [ "書籍1", "書籍2", "書籍3"]
+    @newest_list = [ {title: "書籍1", create_at: DateTime.now},
+                     {title: "書籍2", create_at: DateTime.now},
+                     {title: "書籍3", create_at: DateTime.now}]
     goPage :user_home
   end
 
@@ -149,10 +159,8 @@ class WebGui < Sinatra::Base
   # @raise [WebError] ユーザ情報編集失敗
   post '/user_edit' do
     id = session[:userId]
-    name = params[:name]
-    full_name = params[:full_name]
-    email = params[:email]
-    try_pass = params[:try_pass]
+    name = params[:name]; full_name = params[:full_name]
+    email = params[:email]; try_pass = params[:try_pass]
     new_pass = params[:new_pass]
     
     if (id == nil)
@@ -172,8 +180,132 @@ class WebGui < Sinatra::Base
       redirect "/user_home"
     rescue UserAccount::NotFoundInstanceError,
            UserAccount::AuthenticationError
-      raise WebError.new(statu: 400, message: "ユーザ情報の編集に失敗しました。", refs: "/user_edit")
+      raise WebError.new(status: 400, message: "ユーザ情報の編集に失敗しました。", refs: "/user_edit")
+    end
+  end
+
+  # 蔵書の登録
+  get '/book_regist' do
+    id = session[:userId]
+    if (id == nil)
+      raise WebError.new(status: 408, message: "セッション期限切れです。再ログインをしてください。")
+    end
+    goPage :book_regist
+  end
+    
+  # 蔵書の登録 (POST)
+  # @post_param isbn [String] ISBN
+  # @post_param title [String] 書名
+  # @post_param volume [Integer] 巻数
+  # @post_param series [String] 単行本シリーズ
+  # @post_param author [String] 著者
+  # @post_param orignal_author [String] 原作者
+  # @post_param illustrator [String] 作画
+  # @post_param translator [String] 翻訳
+  # @post_param supervisor [String] 監修
+  # @post_param publisher [String] 出版社
+  # @post_param pubdate [Date] 出版日
+  # @post_param cover_uri [String] イメージURI
+  # @post_param cover_file [Hash] イメージファイル情報
+  # @post_param cover_base64 [String] イメージ情報(Base64)
+  # @post_param summary  [String] 蔵書概要
+  # @post_param rank [Integer] 蔵書評価(0-5)
+  # @raise [WebError] セッションの期限切れ
+  # @raise [WebError] 蔵書情報編集失敗
+  post '/book_regist' do
+    id = session[:userId]
+    book_info = Hash.new
+
+    if (id == nil)
+      raise WebError.new(status: 408, message: "セッション期限切れです。再ログインをしてください。")
+    end
+
+    # 書影の新規登録があるかを確認
+    image_f = false
+    if (book_info[:cover_base64] != null)
+      image_f = true
+    end
+    
+    params.each do |key, value|
+      case key
+      when :sammary, :rank, :cover_base64, :cover_file
+        # 対象キーは書籍情報ではないので飛す
+        next
+      end
+      if ((key == :cover_uri) && (image_f))
+        # 登録するイメージがあるのでURIの登録は飛す
+        next
+      end
+      book_info[key] = value
+    end
+
+    begin
+      isbn = book_info[:isbn]
+      # 書籍情報の更新
+      if (BookManager.isBook(isbn))
+        BookManager.updateBook(isbn, book_info)
+      else
+        BookManager.createBook(book_info)
+      end
+      
+      # 書影情報の更新
+      if (image_f)
+        data = Base64.decode64(book_info[:cover_base64])
+      end
+      if ((not image_f) && (book_info[:cover_uri] == nil) &&
+          (params[:cover_file] != nil))
+        data = getUploadData(params[:cover_file])
+      end
+      if (data != nil)
+        image_hash = BookManager.addBookCover(isbn, data)
+        cover_uri = '/book_image/' + image_hash
+        BookManager.updateBook(isbn, cover_uri: cover_uri)
+      end
+
+      # 蔵書情報の更新
+      BookManager.createBookCollect(isbn, id, params[:summary], params[:rank])
+      
+    rescue BookManager::NotFoundInstanceError,
+           BookManager::AlreadyInstanceError
+      raise WebError.new(status: 400, message: "蔵書情報の登録に失敗しました。", refs: "/book_regist")
+    end
+    redirect "/book_info/#{isbn}"
+  end
+
+  # ISBN からの書籍情報を検索する
+  # @post_param [String] isbn 検索対象のISBN
+  # @raise [WebError] セッションの期限切れ
+  # @raise [WebError] 登録済みの蔵書だった。
+  post '/book_search_isbn' do
+    if (id == nil)
+      raise WebError.new(status: 408, message: "セッション期限切れです。再ログインをしてください。")
+    end
+    
+    isbn = params[:isbn]
+    begin
+      @book = searchISBN(isbn, id)
+    rescue BookManager::AlreadyInstanceError
+      raise WebError.new(status: 409, message: "あなたの蔵書にすでに該当する書籍があります。", refs: "/book_regist")
+    end
+    goPage :book_regist
+  end
+  
+  # ISBN からの書籍情報を検索する
+  # @post_param [Hash] cover_file イメージファイル情報
+  # @raise [WebError] セッションの期限切れ
+  post '/book_upload_cover' do
+    if (id == nil)
+      raise WebError.new(status: 408, message: "セッション期限切れです。再ログインをしてください。")
+    end
+    
+    @book = params
+    data = getUploadData(params[:cover_file])
+    if (data != nil)
+      base64 = Base64.encode64(data)
+      @book[:cover_base64] = base64
+      @book[:cover_uri] = "data:image/jpeg;base64," + base64
     end
+    goPage :book_regist
   end
   
   # ログアウトページ
index 18af0f2..754824a 100644 (file)
@@ -268,7 +268,16 @@ class BookManager
       raise DbAccessError
     end
   end
-  
+
+  # 書籍存在チェック(ISBN)
+  # @param [String] isbn_str 探索対象のISBN
+  # @return [Boolean] 対象書籍の有無を確認
+  def self.isBook(isbn_str)
+    isbn = toIsbn(isbn_str)
+    book = Book.find_by(isbn: isbn)
+    return book != nil
+  end
+
   # 書籍探索(ISBN)
   # @param [String] isbn_str 探索対象のISBN
   # @return [Hash] 書籍情報
@@ -295,8 +304,8 @@ class BookManager
     end
     book = Book.new
     book_info.each do |key, value|
-      if (key == :cover_image)
-        # 書影のイメージはここでは設定しない
+      if ((key == :cover_image) || (key == :isbn))
+        # æ\9b¸å½±ã\81®ã\82¤ã\83¡ã\83¼ã\82¸ã\81¨ISBNã\81¯ã\81\93ã\81\93ã\81§ã\81¯è¨­å®\9aã\81\97ã\81ªã\81\84
         next
       end
       if (key == :cover_uri)
@@ -448,12 +457,12 @@ class BookManager
     return createBookHash(book, book_collect)
   end
   
-  #蔵書情報を登録
-  #@param [String] isbn 登録するISBN
-  #@param [Integer] user_id 登録対象のユーザID
-  #@param [String] summary ユーザ毎の紹介分
-  #@param [Integer] rank ユーザの評価
-  #@return [BookCollection]  蔵書情報
+  # 蔵書情報を登録
+  # @param [String] isbn 登録するISBN
+  # @param [Integer] user_id 登録対象のユーザID
+  # @param [String] summary ユーザ毎の紹介分
+  # @param [Integer] rank ユーザの評価
+  # @return [BookCollection]  蔵書情報
   def createBookCollect(isbn, user_id, summary, rank)
     if (BookCollection.find_by(isbn: isbn, user_id: user_id) != nil)
       raise NotFoundInstanceError
@@ -503,11 +512,25 @@ class BookManager
       end
     end
   end
+
+  # 蔵書の新規登録リスト取得
+  # @param [Integer] user_id 取得対象のユーザID
+  # @return [Array<Book>] 取得した書籍情報
+  def self.newerListOfBooks(user_id, num)
+    books = Array.new
+    book_collects = BookCollection.where(user_id: user_id).
+                      oder(create_at: :desc).first(num)
+    book_collects.each do |item|
+      book = Book.find_by(isbn: item.isbn)
+      books.push(book)
+    end
+    return books
+  end
   
   # 蔵書情報の削除
   # @param [String] isbn_str 削除対象のISBN
   # @param [Integer] user_id 削除対象のユーザID
-  def self.deleteUser(isbn_str, user_id)
+  def self.deleteBookCollect(isbn_str, user_id)
     isbn = toIsbn(isbn_str)
     book_collect = BookCollection.find_by(isbn: isbn, user_id: user_id )
     if (book_collect == nil)
diff --git a/sinatra/app/views/coffee/book_regist.haml b/sinatra/app/views/coffee/book_regist.haml
new file mode 100644 (file)
index 0000000..a33afd9
--- /dev/null
@@ -0,0 +1,114 @@
+- # encoding: utf-8
+- admin_f = @admin_f
+- id = @id
+- book_info = @book_info
+
+%h3
+  新規に蔵書の情報を登録することができます。
+
+.message
+  「ISBN探索」を押下すると、該当する本の情報が取得できます。
+.message
+  「書影Upload」を押下すると、本の書影を登録できます。
+  
+
+%hr
+
+%form{ :action => "/book_regist", :method => "post"}
+  .formstyle
+    .params
+      .item
+        %label{ :for => 'isbn' }
+          %span
+            ISBN:
+        %input{ :name => 'isbn', :type => 'text', :id => 'isbn', :value => book_info[:isbn], :readonly => (isbn != nil) }
+        %input{ :type => 'submit', :class => 'side_button', :value => 'ISBN探索', formaction => '/book_search_isbn' }
+
+      .item
+        %label{ :for => 'title' }
+          書名:
+        %input{ :name => 'title', :type => 'text', :id => 'title', :value => book_info[:title]}
+      
+        %label{ :for => 'volume' }
+          %span
+            巻数:
+        %input{ :name => 'volume', :type => 'text', :id => 'volume', :size => 3, :value => book_info[:volume]}
+        
+      .item
+        %label{ :for => 'series' }
+          %span
+            単行本シリーズ:
+        %input{ :name => 'series', :type => 'text', :id => 'series', :value => book_info[:series]}
+        
+      .item
+        %label{ :for => 'author' }
+          %span
+            著者:
+        %input{ :name => 'author', :type => 'text', :id => 'author', :value => book_info[:author]}
+
+      .item
+        %label{ :for => 'original_author'}
+          %span
+            原作者:
+        %input{ :name => 'original_author', :type => 'text', :id => 'original_author', :value => book_info[:orignal_author]}
+
+      .item
+        %label{ :for => 'illustrator' }
+          %span
+            作画:
+        %input{ :name => 'illustrator', :type => 'text', :id => 'illustrator', :value => book_info[:illustrator]}
+      
+      .item
+        %label{ :for => 'translator' }
+          %span
+            翻訳:
+        %input{ :name => 'translator', :type => 'text', :id => 'translator', :value => book_info[:translator]}
+
+      .item
+        %label{ :for => 'supervisor' }
+          %span
+            監修:
+        %input{ :name => 'supervisor', :type => 'text', :id => 'supervisor', :value => book_info[:supervisor]}
+       
+      .item
+        %label{ :for => 'publisher' }
+          %span
+            出版社:
+        %input{ :name => 'sublisher', :type => 'text', :id => 'publisher', :value => book_info[:publisher]}
+       
+      .item
+        %label{ :for => 'pubdate' }
+          %span
+            出版日:
+        %input{ :name => 'pubdate', :type => 'date', :id => 'pubdate', :value => book_info[:pubdate]}
+        
+      .item
+        %label{ :for => 'cover_file' }
+          %span
+            書影:
+        - if cover_uri != nil
+          %image{ :border => '1', :src => cover_uri, :class => 'cover_image', :width => '128', :height => '182'}
+        - if cover_base64 != nil
+          %input{ :name => 'cover_base64', :type => 'hidden', :value => book_info[:cover_base64]}
+        %input{ :name => 'cover_file', :type => 'file', :id => 'cover_file', :accept => 'image/png, image/jpeg'}          
+        %input{ :type => 'submit', :class => 'side_button', :value => '書影Upload', formaction => '/book_upload_cover' }
+
+      .item
+        %label{ :for => 'summary' }
+          %span
+            概説:
+        %textarea{ :name => 'summary', :rows => '5', :cols => '35', :id => 'summary'}
+          #{book_info[:summary]}
+
+      .item
+        %label{ :for => 'rank' }
+          %span
+            評価:
+        %input{:name => 'rank', :type => 'text', :id => 'rank', :value => book_info[:rank], :pattern => '[0-5]'}
+        
+    .buttons
+      %hr
+      %input{ :type => 'submit', :class=>'push_button', :value => '送信'}
+      %input{ :type => 'button', :class=>'push_button', :onclick =>"location.href='/user_home'", :value => 'もどる' }
+  
+  
diff --git a/sinatra/app/views/coffee/check_form.coffee b/sinatra/app/views/coffee/check_form.coffee
new file mode 100644 (file)
index 0000000..b87061f
--- /dev/null
@@ -0,0 +1,20 @@
+window.checkDifferentForm  = (my_form, other_id, message) ->
+  other_form = document.getElementById(other_id)
+  my_value = my_form.value
+  other_value = other_form.value
+
+  if (other_value != "") && (other_value == my_value)
+    my_form.setCustomValidity(message)
+  else
+    my_form.setCustomValidity('')
+
+window.checkSameForm = (my_form, other_id, message) ->
+  other_form = document.getElementById(other_id)
+  my_value = my_form.value
+  other_value = other_form.value
+
+  if (other_value != "") && (other_value != my_value)
+    my_form.setCustomValidity(message)
+  else
+    my_form.setCustomValidity('')
+  
index 3908d7f..bca1f72 100644 (file)
@@ -11,7 +11,7 @@
     %title
       #{title_name}
     %link{ :rel => 'stylesheet', :href => '/css/style.css'}
-    %script{ :src => '/scripts/default.js'}
+    %script{ :src => '/scripts/check_form.js'}
   %body
       
     - if  user_name == nil
index 05b92cb..d8d254e 100644 (file)
@@ -2,7 +2,9 @@
 
 %h3
   ユーザーログイン
-
+  
+.message
+  アカウント名とパスワードを入力してください。
 %hr
 
 %form{ :action => "/login", :method => "post"}
index 8b1baad..937f723 100644 (file)
@@ -36,7 +36,7 @@ input.push_button{
     background: #f8e58c;
     align-items: center;
     text-align: center;
-    height: 20em;
+    height: 25em;
     padding: 20px 5px;
 }
 
@@ -67,7 +67,7 @@ input.push_button{
     background: #f8e58c;
     align-items: center;
     text-align: center;
-    height: 32em;
+    height: 30em;
     padding: 5px 0px;
     overflow: auto;
 }
@@ -84,20 +84,11 @@ input.push_button{
     text-align: left;
 }
 
-.buttons {
-    margin: 20px 0px;
-    position: absolute;
-    bottom: 0;
-    left: 0;
-    right: 0;
-    margin: 0px auto;
-    padding-bottom: 20px;
-
-}
-
 .formstyle {
     margin: 0, auto;
     .params {
+        height: 15em;
+        overflow: auto;
         margin-left: 20px;
         text-align: left;
         display: block;
@@ -113,6 +104,17 @@ input.push_button{
     }
 }
 
+.buttons {
+    margin: 5px 0px;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    hight: 5em;
+    margin: 0px auto;
+    padding-bottom: 20px;
+}
+
 .side_item {
     padding: 5px 5px;
     margin: 2px 0px;
index af72432..83de15b 100644 (file)
@@ -2,7 +2,8 @@
 
 %h3
   ユーザ登録
-%p
+  
+.message
   ユーザのアカウントを登録します。 以下を入力してください。
 
 %hr
@@ -32,7 +33,7 @@
         %label{ :for => 'passwdConfirm'}
           %span
             パスワード(確認用):
-        %input{ :type => 'password', :id => 'passwdConfirm', :pattern => '.{6,}', :required => true, :oninput => 'checkPasswd(this)' }
+        %input{ :type => 'password', :id => 'passwdConfirm', :pattern => '.{6,}', :required => true, :oninput => 'checkSameForm(this, "passwd", "パスワードが一致しません。")' }
 
       .item
         %label{ :for => 'email' }
index bf8283d..da45f5b 100644 (file)
@@ -6,7 +6,7 @@
 - email = @email
 
 %h3
-  #{username} のユーザデータを変更できます。
+  #{username} ã\81\95ã\82\93ã\81®ã\83¦ã\83¼ã\82¶ã\83\87ã\83¼ã\82¿ã\82\92å¤\89æ\9b´ã\81§ã\81\8dã\81¾ã\81\99ã\80\82
 
 .message
   パスワードを変更する際には、現在のパスワードと
         %label{ :for => 'passwd' }
           %span
             新しいパスワード:
-        %input{ :name => 'new_pass', :type => 'password', :id => 'passwd', :pattern => '.{6,}', :oninput => 'checkOldPass(this)' }
+        %input{ :name => 'new_pass', :type => 'password', :id => 'passwd', :pattern => '.{6,}', :oninput => 'checkDifferentForm(this, "old_passwd", "現在のパスワードと新しいパスワードが同じです。")' }
 
       .item
         %label{ :for => 'passwdConfirm'}
           %span
             新しいパスワード(確認用):
-        %input{ :type => 'password', :id => 'passwdConfirm', :pattern => '.{6,}', :oninput => 'checkPasswd(this)' }
+        %input{ :type => 'password', :id => 'passwdConfirm', :pattern => '.{6,}', :oninput => 'checkSameForm(this, "passwd", "新しいパスワードが一致しません。")' }
 
       .item
         %label{ :for => 'email' }
@@ -62,7 +62,7 @@
       
     .buttons
       %hr
-      %input{ :type => 'submit', :class=>'push_button', :value => '送信'}
-      %input{ :type => 'button', :class=>'push_button', :onclick =>"location.href='/user_home'", :value => 'もどる' }
+      %input{ :type => 'submit', :class => 'push_button', :value => '送信'}
+      %input{ :type => 'button', :class => 'push_button', :onclick =>"location.href='/user_home'", :value => 'もどる' }
   
   
index f49ebbf..183e806 100644 (file)
@@ -2,13 +2,14 @@
 - user_name = @username
 - newest_list = @newest_list
 
-%h2
+%h3
   ここは #{user_name} さんのホームページです
 
 .message
   あなたの最近登録した本は以下になります。
 
 %ul
-  - newest_list.each do |i|
-    %li=  i
+  - newest_list.each do |item|
+    %li  #{item[:title]} (登録日時:#{item[:create_at].strftime("%Y/%m/%d %T")})
+
     
diff --git a/sinatra/public/scripts/default.js b/sinatra/public/scripts/default.js
deleted file mode 100644 (file)
index 0d7fe2f..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// メールのフォームチェック用
-
-function checkEmail(input){
-  var mail = document.getElementById("email").value; //メールの値を取得
-  var mailConfirm = input.value; //メール確認用の値を取得(引数input)
-
-  // パスワードの一致確認
-  if(mail != mailConfirm){
-    input.setCustomValidity('メールアドレスが一致しません'); // エラーメッセージのセット
-  }else{
-    input.setCustomValidity(''); // エラーメッセージのクリア
-  }
-}
-
-// パスワードのフォームチェック用 (新旧の確認)
-function checkOldPass(input){
-  var old_passwd = document.getElementById("old_passwd").value; //旧パスワードの値を取得
-  var new_passwd = input.value; //新パスワードの値を取得
-
-  // パスワードの一致確認
-  if((old_passwd != "")  && (old_passwd == new_passwd)){
-    input.setCustomValidity('現在のパスワードと新しいパスワードが同じです。'); // エラーメッセージのセット
-  }else{
-    input.setCustomValidity(''); // エラーメッセージのクリア
-  }
-}
-
-// パスワードのフォームチェック用 
-function checkPasswd(input){
-  var passwd = document.getElementById("passwd").value; //パスワードの値を取得
-  var passwdConfirm = input.value; //パスワード(確認用)の値を取得
-
-  // パスワードの一致確認
-  if(passwd != passwdConfirm){
-    input.setCustomValidity('パスワードが一致しません。'); // エラーメッセージのセット
-  }else{
-    input.setCustomValidity(''); // エラーメッセージのクリア
-  }
-}