【2020/05/19】SPA開発カテゴリーの記事更新を終了します。
皆様。お久しぶりです。@andouです。
皆様には大変申し訳ありませんが、この「SPA開発」カテゴリーの記事更新を一旦終了といたします。
理由は、優先すべきことが増え、このカテゴリーに時間を割けなくなったためです。
今ままいつか更新するかもと思わせぶりな状況は、読者の皆様に迷惑をかけると思いまして、今回お伝えすることにしました。
なお、質問は随時承っております。下記リンクの「Slackで質問する」ボタンをクリックし、Slackにご参加ください。
「独学プログラマ」の内容についてSlackで質問できるようになりました
今まで「SPA開発」のカテゴリー記事を読んでくださり、本当にありがとうございました。
完?
.
.
.
実は、このSPA開発カテゴリーの続編として、新たなプロジェクトが始動します。
正式な動きがありましたら、このブログでお伝えします。
お楽しみに!
この記事には?
現在「 Rails apiとNuxt.jsでSPA開発」の元ネタとなるアプリを開発しています。
この記事には、そのアプリ開発の進捗状況が記載されています。
アプリ開発が落ち着いたら、記事にまとめアップしていきます。
記事の更新が止まって本当に申し訳ないです。
2020年1月末を目処に、記事更新を再開します。もう少々お待ちください。。。
※上から順に最新の情報となっています。
開発中のアプリ
下記URLにて公開されています。
ソースコード共有します
必要であれば、ソースコードを共有します。
必要とする機能・コードを明記の上、slack よりご連絡ください。
【02/12】会計年度が追加できるようになりました
- タブのレイアウトを一新
- 決算月とタイトルをボタンクリックで自動セットできるように
- 作成した会計年度はテキストの色を変えハイライト表示
- テーブルコンポーネントを作成し、編集ページと共有化
- ブログ更新せな...
- 開発で手一杯
- ごめんなさい
【02/03】会計年度が編集できるようになりました
- 編集後の値は青文字でハイライト表示するようにしました。Railsから返される会計年度の配列は期首順に並び替えされています。このままでは、編集後の会計年度をユーザーが見失う可能性があるためこのような実装としました。
- Railsからは、新しく現在の会社のjsonを返します。その会社のjsonには
as_json
のinclude
を使って会計年度配列を紐づけています。 - models/company.rb
def my_json
as_json(
only: Company.json_columns,
include: {
periods: AccountingPeriod.include_json
}
)
end
【01/28】会計年度を管理するページのレイアウトを実装しました
- チェックを入れるとdeleteリンクを表示
- 編集マーククリックでダイアログの出現
- 期首を選択すると決算月が自動で11ヶ月後の日付になる
次はボタンを用意してRails Apiと繋ぐ作業ですね
【01/19】会計期間モデルを作成し、会社トップページに表示しました。
- 数値の単位を選択する、VuetifyのselectBoxを小さくするCSSに苦戦しました。
- コンポーネントに
small
のkeyを渡した場合にCSSクラスをセットするようにしています。 - components/unitSelectBox.vue
<template>
<v-select
:class="[small && 'my-small-select']"
/>
</template>
<style lang="scss">
.my-small-select {
.v-input__slot, .v-select__slot, .v-select__selections, .v-select__selection--comma {
min-height: 25px !important;
max-height: 25px !important;
}
.v-input__slot {
padding: 0 8px !important;
font-size: .75rem;
}
.v-select__selection--comma {
margin: 0;
}
.v-input__append-inner {
margin-top: 0 !important;
}
.v-select__selections {
align-items: unset;
}
}
</style>
【01/17】会社が削除できるようになりました
destroy
アクションは簡単です。Railsさまさまです。- companies_controller.rb
def destroy
@company.destroy!
render_json(
"success",
"#{@company.name}を削除しました",
{ companyId: @company.id }
)
end
【01/12】会社が編集できるようになりました
- 会社の更新が成功した場合は、Railsから返された会社オブジェクトをvuexの会社と会社の配列に追加しなければならず、実装に苦戦しました。
1、編集ページから新しい会社オブジェクトをdispatchします。
this.$store.dispatch('company/setResponse', company)
2、VuexのアクションでcurrentCompanyにセットします。同時に会社の配列も入れ替えます。
setResponse ({ commit }, company) {
commit('setCurrentCompany', company)
commit('spliceCompanies', company)
}
3、ミューテーション内の会社配列の入れ替えでは、idから旧会社オブジェクトを検索し存在すればsplice
で削除します。その後、新会社オブジェクトをunshift
で先頭に追加します。
このメソッドは、会社の新規作成時にも使いまわせるようターゲットが存在した場合のみ削除を実行します。
4、かなり遠回りしましたが、すっきりとしたVuexとなりました。(おしまい)
spliceCompanies (state, company) {
const target = state.companies.find(com => com.id === company.id)
// targetが存在した場合に要素を削除する
if (target) {
const index = state.companies.indexOf(target)
state.companies.splice(index, 1)
}
state.companies.unshift(company)
}
【01/09】ログイントップページのレイアウトが完成しました
- 新規作成ダイアログは、どこからでも呼び出せるようグローバルイベントに登録しています。
【01/08】会社の新規作成ダイアログが完成しました
- Vuetifyのダイアログに一番時間を取られました。
- ダイアログの上にトースターを出力すると、トースターを閉じると同時にダイアログも閉じられます。
- これでは、エラートースターを出力させることができません。
- この課題を解決する
v-dialog
のプロパティは以下の2つです。- persistent => アウトサイドをクリックしてもダイアログを閉じない
- no-click-animation => アウトサイドをクリック時のアニメーションを無効にする
以上!
【01/07】会社のミニメニューができました
- とほほ。大変でした。
【01/05】会社の個別ページが表示できるようになりましたyo!
- 大変でした。最初はFirebaseのレイアウト設計をパクってやろうと、会社に
slug
パラメーターを持たせ動的なルーティングで表示しました。 - これが大きな間違いでした。会社を作成するたびにgenerateコマンドを自動で実行し、サーバー側で動的ルーティングを生成しなければなりません。
- そんなことNuxt.jsでどうやってするのか。。答えは見つからずDB設計からやり直しました。
- 結果、ユーザーモデルに会社IDを持たせ、動的なルーティングを生成しなくても選択中の会社を表示するようにしました。
- すごいぞFirebaseレイアウト設計!!
【01/04】ユーザーがもつ会社一覧が表示できるようになりました
【12/30】アカウントが削除できるようになりました☺️
【12/29】パスワードの変更ページが完成しました
【12/29】アカウント設定のページレイアウトが完成しました
【12/29】メールアドレス変更ページが完成しました
- 新しいメールアドレスが入ったtokenを発行し、受け取ったコントローラーアクションで解析しています。
【12/27】パスワードリセットページが完成しました
- これにてユーザー認証周りは全て完了です。
【12/20】ログイン機能の実装が完了しました
- 下記gifは、ログイン機能とリダイレクト機能の実装デモです。
【12/18】ログイン前ユーザーのリダイレクト処理が実装できました
- 実装は以下のとおりです。
- ログイン前のユーザーがログイン必須ページにアクセスしようとしたとき、
- そのURLをVuexで記憶し、
- ログイン直後にリダイレクトする
middleware/redirect.js
export default ({ app, store, route, redirect }) => {
// アプリに存在するルートがある場合のみ処理を行う
if (store.state.allRouteNames.includes(route.name)) {
const allAccessible = [
'index',
'password-resets',
'password-new',
'account-activations',
'logout'
]
// アクセス可能なURLの時、処理をストップする
if (allAccessible.includes(route.name)) { return false }
const logoutOnlyPages = ['signup', 'login']
// ログイン中のユーザーをリダイレクトする
if (store.state.loggedIn && logoutOnlyPages.includes(route.name)) {
return redirect('/')
}
// ログアウト中のユーザーをリダイレクトする
if (!store.state.loggedIn && !logoutOnlyPages.includes(route.name)) {
// ログイン前のURLを記憶する
if (route.fullPath !== '/') {
store.dispatch('getRedirectPath', route.fullPath)
}
app.$my.toasterSetTimeout({ msg: 'ログインが必要です' })
return redirect('/login')
}
}
}
【12/16】解析したトークンをローカルストレージに保存できるようになりました
- Nuxt.js側のトークン解析は、jwt-decodeを使用しています。
【12/15】本番環境でAWSから認証メールを送信できるようになりました
- gem aws-sdk-rails を使用しています。
【12/13】Rails6.0でjwt認証用のgem「knock」をセットアップしました
- 画像の黄色文字がknockで発行されたトークンになります。
【12/12】トースターが完成しました
this.$nuxt.$on
this.$nuxt.$emit
を使ってグローバルで呼び出せるよう設定しています。
【12/10】ログイン後に表示されるナビゲーションドロワーを実装しました
- ウィンドウ幅は「$vuetify.breakpoint.width」で取得しています。
- computedで960未満のときtrueを返すプロパティを作成し、ボタン表示を切り替えています。
【12/9】パスワードリセットページのフロントエンドが完成しました
【12/8】ログイン周りの各ページレイアウトが完成しました
各ページそれぞれのページレイアウトが完成しました。
- 会員登録フォーム
- ログインフォーム
- パスワードリセットフォーム
- 新規パスワード登録フォーム