野球リーグスコア管理システムとキャップ野球情報局に関する進捗です。
旧システムについてはこちらの記事をご覧ください。
robotoフォントのfont-weight700を使っているので、敢えてテーブルヘッダを太字ではないようにして区別する
参考スタイル:Baseball LAB
コンテンツ詰め込むにはもうこれしか方法がないなーと思います。
スマホ版だけコンテンツ削るという手法もありだとは思いますが。
同僚のデザインできる方にレビューしていただきました。
本日は指摘事項をいくつか反映してタイムアップ。
.current:before{
content: '\f101';
font-family: 'Font Awesome 5 Free';
font-weight: bold;
padding-right:5px;
}
.current{
pointer-events: none;
}
ページごとにシェアするURLを動的にしたいのでまだ課題として置いておきます。
参考にした記事:Twitterシェアボタンの設置 - Qiita
ふとIE11で表示させてみたら真っ白に近かったので急遽対応しました。下記記事のbabel-polyfill入れてindex.jsでインポートする方を採用しました。
参考記事:Reactアプリを IE11 で表示すると 「オブジェクトは 'startsWith' プロパティまたはメソッドをサポートしていません。」 が発生する
1/17のボードでシーズンをプルダウンで選択する方式にしたのですが、他の箇所でアコーディオン化に成功して思いのほかよかったのでこちらもアコーディオン化しました。
ただ、苦労したのはアコーディオンの中に格納したテーブルの横幅。
テーブルの中で表示するコンテンツが多く、結局paddingで5px程度取っても横幅が足りなくなるのでfont-sizeを下げることにしました。
シーズンごとにリストアイテム化していた試合日ですが、
今回アコーディオンの中に格納しました。
コンポーネントごとにstateを持ってdisplay:noneを切り替える方法を考えていたのですが、CSSで作るとトランジションが使えて表現が豊かになるのでこちらに変えました。
参考:CSSだけでアコーディオンを作る方法
昨日の時点でheightが0になってしまってどうしようもなかった問題ですが、
1. BootstrapTableにidを設定する
BootstrapTableにはidというプロパティがないので外側のdivに設定しました。
return (
<div className='col s12'
id={this.props.id}>
<BootstrapTable
keyField={this.props.keyField}
data={this.props.data}
columns={this.props.columns} />
</div>
)
document.getElementById('trophy').clientHeight + 22
this.setState({
height:document.getElementById('trophy').clientHeight
})
style={
{ height: this.state.height}}
元々スライドメニューはあったのですが完成度が低かったので途中からコメントアウトしていました。
メニューを選択するとfocusで意図しないスタイルが適用されていたので背景色に同化してごまかしましたw
.bm-item:focus {
outline-color: darkcyan;
}
カード化すると見栄えがよくなりました。
ただ、react-bootstrap-tableをカードでラップしようとするとカードのheightが0になってしまってちょっと悩みどころ。
ずっと公開はしていたのですが、
- UIがだいぶマシになってまともに見られるようにはなった
- UIの修正が一段落ついた
- メニューを実装して導線が張れた
ということで、crieitのサービスのレビュー掲示板でレビューを募集しています。
昨日記事書けなかったので今日書きます。
カード型コンテンツの配色パターンの決め方があったので参考にしてだいぶ改良しました。アクセントカラーはどこに置けばいいかわからずに結局すごく目立つところに置いてます。
react-sticky-footer
コピーライトとかの表記ですね。
フッタがスクロール中は半透明になり、一番下までいくと指定したスタイルで見える、というコンポーネントです。
reactのwindow.locationではページをフレーム内で表示していても、現在ブラウザがどこで表示しているか判定できないようだったので結局public/index.htmlにべた書きしました。
<script type="text/javascript">
if (top!=self) {
top.location.href=self.location.href;
}
</script>
勝利・敗戦・セーブ・HRを記録した選手に選手ページへのリンクを追加しました。これでトップページ(試合開催日一覧)→試合結果→選手個人ページへの導線まではできたことになります。
肝心のスタッツが独立しているという。
リーグのコンテンツとして試合動画を撮っているので上手く活用したいところです。
今回はreact-youtubeというパッケージを使っています。
定石としてはDBにカラム作ってAPIで返すべきなのだとは思いますが、今回はjsonですらないです。
ということで試合IDをキーとしてyoutubeの動画IDを格納するファイルを作りました。
DBに追加するのと手間は同じぐらいだと思います。
export const youtubeConfig =
{
//日付などのコメント
"試合ID":"youtube動画ID",
}
これをreact内のループでこう書いてやります。
import { youtubeConfig } from './youtubeConfig'
(中略)
<YouTube
videoId={youtubeConfig[試合ID]}
/>
個人開発でcalcを使ったのは初めてです。
業務でもそんなに使ったことはないのですが...。
ブラウザの幅に応じて動画の幅を拡大縮小し、高さをアスペクト比を維持するように変えてやります。
iframe{
width: 90%;
height: calc(90vw*9/16);
}
react-bootstrap
Reactを使われている方は馴染みがあるかと思いますが、
0.32.4までがbootstrap3に対応しており、bootstrap4対応によって0.32.4から1.0.0-betaまで一気にバージョンが上がりました。
公式ではbootstrap3系と4系は分けてサポートしていくとアナウンスされています。
昨年9月に1.0.0-betaがリリースされていましたが、知ったのは昨日。しかも「ドキュメントのフォーマットちょっと変わったなー」ぐらいの認識で見ていたのと、Cardコンポーネントが新たに追加されていたのでそちらの実装に気を取られていたのとでbreaking changeに気づいたのが今朝。昨夜デプロイしてたので一晩メインのページが落ちた状態でした...。
昨夜実装したコンポーネントをコメントアウトして一旦デプロイしなおし、エラー箇所のソースを確認していた際にようやくbreaking changeに気づく。Cardコンポーネントがある4系に寄せるか、3系に戻してCardコンポーネントがない状態で対応するか少し迷いましたがとりあえず3系に戻してCardはmaterializeCSSで対応しました。元々ベースのデザインにmaterializeCSSを採用しています。
結局昼休み30分ぐらい使って何とか直して再デプロイ。
とりあえずreact-bootstrapのListGroup.itemを使って日付の一覧を入れ子で実装。アコーディオン化したいが時間ないので仮置き。
UIは練らないといけないが日付→日付別試合一覧への導線は完成。
1日に3-5イニングの試合を3-5試合行うので日別の試合結果一覧ページを実装。投手成績とHRの本数を取得する処理が割と面倒で、試合直前までの成績を取得した後にその試合での成績を合算する処理をしないといけない。HR本数の取得処理は旧システムでも行っていたのでSQLをそのまま移植できると思っていたが、
その日までに成績がなく、その日の一番最初の試合に1号HRを打つとSQLで取得できないバグがあることに気づいた。
修正後のSQL
select
h.player_id,
name,
homerun,
before_homerun_count
from
(SELECT
b.player_id,
name,
homerun
FROM batting_sum b
inner join player p on p.id = b.player_id
WHERE b.game_id= ? and b.homerun>=1
group by player_id) h
left outer join (
select
b.player_id,
sum(homerun) as before_homerun_count
from batting_sum b
inner join game g on g.game_id=b.game_id
where
((game_date>= ? and game_date< ?)
or (game_date= ? and game_number<= ? ))
group by player_id) sum_homerun
on h.player_id = sum_homerun.player_id
あとはSQLの引数を渡す順番を間違えていて2時間ぐらい結果が取得できなくて嵌ってしまった。。
現在入力している全てのシーズンのデータから通算成績を取得する処理を実装しました。
react側は旧システムAPIであらかじめ作っていたのもあって、
これにはそんなに時間がかかりませんでした。
本日、2019年度前期シーズン開幕戦でした。
現行のReact/NodeJS/Netlifyのシステムでは初めての本格運用が始まります。
スコアの速報を入力していたのですがサーバサイド側で打率が0のときに打撃十傑から除く処理が抜けていたことに気づいてスコア入力を中断してシステムの修正を行うなど。
ここのところreactでOGPを動的に変える方法を模索していて進捗が出ていませんでした。
これまでスタッツページから個人の成績ページへの遷移は打率タブの名前欄のみ実装していましたが、ノンタイトル以外のタブで個人成績へジャンプできるように実装しました。
また、選手名をマウスオーバーした際にスタイルを変えるよう実装しました。
旧システムではAPI化していなかったものをAPI化してトロフィアイコンを組み込んでみました。
react-helmetを使用してmetaタグを書き換えるとページごとにOGPを生成できるのではないかと思ったが、結果としては動的に生成している部分のタグが認識されず。
SSRしないとできない模様
期毎投球成績を返すAPIを実装しました。
ドロップダウンでシーズンを選択するコンポーネントを「シーズンセレクタ」と呼んでいますが、期毎打撃成績と期毎投球成績タブで共通のコンポーネントとする実装を行いました。
何となくマテリアルデザインを使っているのですが、
「マテリアルデザインではタブを入れ子にしてはいけない」というルールをつい先日知りまして。
タブの代わりにドロップダウンでシーズンを選択するように修正しました。
UX的にどうなんですかねー?
[UI]
[API]
[API]
フォーム(UI)と入出力の形が一致していないのでどこかで策定する必要あり。