【WEBアプリ】皆で作る本棚

最終更新日時を読み込み中です…

最近、予定を忘れてしまうことが多くて、非常に困っています。

そして迷惑をかけてしまっていることに、大変申し訳なく思っています。

やはり忘れてしまわないためには、記録することが重要です。

そして、記録したものは見やすく管理することで、役立てられます。

現在、記録して見やすく管理するということを目標としたWEBアプリを開発しています。

その名も、「Mintana」(仮称)です。

このアプリでは、本を管理できます。自分が持っている本をWEB上で登録し、オンライン本棚を作成することができます。

でも、そんな機能を持ったサービスはいっぱいあります。

例えば、ブクログとか。

でも、このアプリは、個人での記録をメインの機能としています。

もしも、家族や友達と共有の本棚を持つことができたら、知識の共有ができたり、話題づくりとなったり、本の貸し借りが楽になったり、メリットが多くあるのではないかと考えました。

そこで、「みんなで一緒に作れる本棚」というコンセプトで開発を行いました。

ここでは、開発中のアプリが、どのようなプログラムで動作しているのか一部抜粋して紹介します。


各画面について


  1. ホーム画面
  2. 本人確認
  3. 本棚作成画面
  4. 本棚

以上の4つの画面によって本システムは構成されています。

それぞれの画面の作成には、「Bootstrap」を用いて作成しています。

今まで、使ってこなかったことを後悔するほどに、楽でした。

なにより、自動的にレスポンシブデザインになってくれるという点で非常に便利で。

ほとんどの画面が、サンプルから少し変えた程度で実装できています。

このホームページも、Bootstrapで書き直したいくらいです。


ホーム画面


主な機能

  • 本棚作成ページへの遷移ボタン
  • 本棚への遷移ボタン
  • アプリ説明欄

このページは、各画面への遷移のためのホーム画面です。

ページの上部には、本棚作成ページへの遷移ボタン、本棚への遷移ボタンがあります。

「作成済みの本棚を探す」というボタンを押すとモーダルが表示されます。

これは、Bootstrapの機能の一つでHTMLだけで簡単に実装出来ます。

このモーダルの中では、本棚IDを入力することで、指定された作成済み本棚ページへと遷移できるようになっています。

本棚IDというのは本棚ページで確認できるようになっています。

ただ、欠陥としてこのIDを忘れた場合には自分の本棚を見つけられなくなってしまいます。

今後の改善項目の一つです。

ボタンの下にはアプリの説明欄を設けています。

こんなのも簡単に作れるのです。


本人確認


ホーム画面の「本棚を作成する」ボタンを押すと次のような画面に遷移します。

この画面では、本人確認のため、メールアドレスの入力を求められます。

入力されたメールアドレスに本棚作成用のURLが送られるという仕組みです。

こちらのページも、もちろんBootstrapでできています。

現在パスワード設定については、機能を使えないようにしています。

セキュリティに関する検証が終わり次第、パスワード設定機能も使えるようになる予定です。

また、パスワードのない本棚も作成可能とする予定です。

パスワードをかけないことで、共有をしやすくすることもできるということです。

プログラムとしては、JavaScriptにて、サーバへとメールアドレスの情報をJSON形式で送信し、サーバ上のPythonでメールを送信するという流れです。

JavaScriptについてはこちらが参考になります。


本棚作成画面


この画面には、本人確認にて送信されたメールからアクセスできます。

しかし、URLを知っていれば誰でもアクセスはできてしまいます。

そこで、Tokenを設定し、時間制限を設けることで、対策をしています。

プログラムとしては、JavaScriptにて、サーバへと本棚の情報をJSON形式で送信し、サーバ上のPythonで本棚を作成するという流れです。

今回、本棚のデータ保存には「sqlite3」を用いています。

データベース操作用に次のようなPythonモジュールを作成し使用しています。


class ControlSqlite3:
    def __init__(self):
        self.connection=None
        self.cursor=None
    
    def fileCheck(self):
        try:
            #create file
            if os.path.isfile(DB_PATH+db_filename):
                pass
            else:
                with open(DB_PATH+db_filename, "x") as f:
                    f.write("")
                os.chmod(DB_PATH+db_filename,0o666)
            return {"message":"ファイルが存在しています","success":True}
        except Exception as e:
            return {"message":"データベース作成に関する問題が発生しました","success":False}

    def connect(self):
        try:
            self.connection = sqlite3.connect(DB_PATH+db_filename,isolation_level=None)
            self.cursor = self.connection.cursor()
            return {"message":"接続成功","success":True}
        except Exception as e:
            return {"message":"接続失敗","success":False}

    def close(self):
        try:
            self.connection.close()
            self.cursor.close()
            return {"message":"切断成功","success":True}
        except Exception as e:
            return {"message":"切断失敗","success":False} 

    def checkTableExsist(self,table_name):
        try:
            sql=f'SELECT COUNT(*) FROM sqlite_master WHERE TYPE="table" AND name="{table_name}"'
            self.cursor.execute(sql)
            res=self.cursor.fetchall()[0][0]
            if not res:
                return {"message":f"{table_name}はありません","success":False}

            return {"message":"実行成功","success":True}
        except Exception as e:
            return {"message":"実行失敗","success":False}

    def view(self,table_name):
        try:
            select_sql = f'SELECT * FROM {table_name}'
            for row in self.cursor.execute(select_sql):
                print(row)
            return {"message":"done.","success":True}
        except Exception as e:
            return {"message":str(e),"success":False}
    
    def getAllTable(self):
        try:
            sql = f'SELECT name FROM sqlite_master WHERE type="table" ORDER BY NAME;'
            for row in self.cursor.execute(sql):
                print(row)
            return {"message":"done.","success":True}
        except Exception as e:
            return {"message":str(e),"success":False}
                        

参考までに。


本棚


主な機能

  • 本の追加
  • 記録した本の検索

これは、本棚の初期画面です。

寂しいですね。本を追加してみましょう。

「本を追加」ボタンを押すと次のようなモーダルが表示されます。

追加の方法は、本のISBN番号を入力するか方法とISBNバーコードをカメラで読み取る方法の2種類です。

検索に成功すると、次のように本のタイトルと「追加」ボタンが表示されます。

追加された本はボタンの下へと追加されていきます。

本によっては表紙が表示されるものもあります。

本が増えてきたら本棚内の本を検索出来たら便利ですよね。

「本を絞り込む」ボタンを押すと次のようなモーダルが表示されます。

「並び替える」では、現在追加順にソートができるようになっています。

今後ソートの方法についても追加予定。

「キーワード」では、本のタイトルをキーワードで検索できます。

それぞれはJavaScriptによって処理しています。

並び替える


function sortByDatetime(bookshelf) {
    bookshelf.sort(function(xx, yy) {
        // undefinedを下に追いやる
        if (!xx.added_datetime_information) {
            return 1
        } else if (!yy.added_datetime_information) {
            return -1
        }

        if (xx.added_datetime_information > yy.added_datetime_information) {
            return -1
        } else if (xx.added_datetime_information > yy.added_datetime_information) {
            return 1
        } else {
            return 0
        }
    })
    showBooks(bookshelf)
}
                        

キーワード


function filterByKeyword() {
    let filter_keyword = $("#filter_keyword").val()
    let filtered_bookshelf = []
    filtered_bookshelf = bookshelf.map(book_info => {
        let pattern = new RegExp(`(.*)${filter_keyword}(.*)`)
        if (book_info.title.match(pattern)) {
            return book_info
        }
        return
    })
    showBooks(filtered_bookshelf)
}
                        

本棚の共有方法について


共有は簡単です。本棚のURLをコピーして共有したい人に送るだけです。

または、本棚IDを共有相手に教えてあげましょう。

本棚IDはホーム画面の「作成済みの本棚を探す」ボタンで使用できます。


おわりに


まだまだ、いろんな機能を追加したいのですが、とりあえず使えそうなところまでできているので公開してみます。

一緒に機能を作ってみたいという人がいたら、ぜひ連絡ください。


参考


このサイトを作った人


水野翔太

福知山公立大学情報学部情報学科
2024年卒業予定

やまもとよしのふゼミ所属 3回生

連絡先:
32045088[at]fukuchiyama.ac.jp
(@マークに置き換えてご利用ください)