recorder-prototype
Firestore+Authendication+Reactでなにか作るで作っているTask Chute時間術式 記録app
実装したもの
テーブル表示
カレンダー表示
demo
/icons2/CodeSandBox.iconhttps://codesandbox.io/s/keen-bash-hv7yw
なぜかVercelへのdeployに失敗する
足りないもの
/icons/done.icon計測中の記録を全てのdeviceで同期させる
現状だとページを変えただけで記録データが消えるのでとても不便
同期する情報
開始時刻
仮の記録名
/users/{userId}の直下に格納すると良さそう
計測中の記録を同期させる | recorder-prototype
/icons/done.icon入力して少し時間が経ったらdatabaseに反映するようにしたい
現状、focusが外れると更新するようになっている
useRef()とdocument.activeElementを併用している
これを自動的に更新するようにしたい
方法
setTimeout()をつかう?
現在記録中の記録名に関しては、入力後1秒後に自動更新するようにした
やった
recorder-prototype#5fc9e6f41280f00000a90008
/icons/done.icon入力欄が下の方にあって押しづらいのを直す
候補
上に置く
/icons/done.icon10:44:36 下に置いて常に固定する
記録を追加するたびにscrollする
とにかく、最新の記録と入力欄がすぐ見える場所にあってほしい
カレンダーから予定を動かせるようにしたい
ss2calendarのとき、そんなに使わなかった割に実装がひたすらめんどくさかった
今回もめんどくさそうなのでパス
drag&dropを実装しないといけない
カレンダーを見やすくする
event blockに時刻を表示しない
やり方がわからん
/icons/done.icon時間間隔を長めにする
timeslotsとstepをいじると似たようなことができる
時間間隔を変える (react big calendar)
/icons/done.iconnav barを固定した
useEffect()を使ってあとからhas-navbar-fixed-topを<body>に追加しないとページ上部が隠れてしまう
おそらくrenderとCSS読み込みの順番が関係しているのだと思う
/icons/done.iconhamburger menuを追加した
JSXでis-activeを操作するようにした
選択操作が正常に動いていない
useEffectの依存からはずした影響
13:02:38 コードを戻してみた
Examples: Row Selection | React Table | TanStack
selectedFlatRowsを使えばRecordIdを取得できる……できるのだが、そこから親componentに値を渡す方法が分からない……
何らかのeventをきっかけに値を親componentに通知することはできる
useEffect()内で通知しようとすると、Maximum update depth exceeded.が発生してしまう
JSONにobjectを変換してから同じかどうか比較して、同じであった場合にsetStateの呼び出しをskipしてみたがだめだった
なぜか5回位呼び出されてしまう
CodePenを使ってReact.jsを学ぶ練習logをもう一度参照して、親componentに値を通知する方法を探すか
13:51:53 これ無理だな
eventを経由して呼び出す以外に方法がない
さらにevent経由で呼び出したとして、何故か正しく反映されない
あとuseTableの返り値をuseTableの引数で使わなければならなかったりしてややこしい
component設計をやり直そう
現状
RecordListにtableのhooksとcomponentを入れている
削除ボタンと削除機能はDashboardページに入れた
変更後
RecordListはcomponentのみ入れる
削除機能などを一つにしたcustom hookを作る
自動更新機能も一緒にする?
一緒にしたほうがいいだろう
DashBoardページからcustom hookを呼び出し、返り値をRecordListに渡す
理想
code:tsx
export const Dashboard = (...) => {
// hooks
const {...} = useRecordList(...);
// components
return <>
<RecordList {...} />
<Delete {...} />
<Copy {...} />
</>
}
15:42:01 設計を一旦断念
時間がない
苦肉の策として、delete buttonをtableの中に入れた
もしかしたら、Buttonなどの操作部品も含めて全て同一のComponentに閉じ込めたほうが良いのかもしれない
実際、React Tableのkitchen sink exampleはbutton含めて全てTableに閉じ込められていた
一旦記録用tableを整理するか
編集用cellを一つに統一する
headerとも一つにまとめたいな
同じ処理を同じところに書きたい
列headerごとにobjectを作るのもありか?
code:ts
{
Header: 'time',
id: 'start-time',
accessor: row => lightFormat(row.start,'HH:mm:ss'),
Cell: ({row})=> {
const {value, onBlur, onChange} = useEditableCell({...});
return <FlexTextArea ... />;
},
}
このデータだけで、その列の表示及び操作方法が決定される
21:54:13 やっぱりReact Tableで行を選択するときに、選択用の列をuseTable()に代入する必要なかった
最初からheaderに入れ込んでおけばいい
22:24:12 とりあえずRecordList.tsxを分割した
recordList/header.tsx
列のheaderの表示方法を定義
recordList/Table.tsx
tableのhtml構造
recordList/RecordList.tsx
本体
だいぶ見やすくなった
22:41:12 てかこのtable genericにできるな
ScheduleListにも使い回せる
いやTableは使い回せない
中で使っているUrlEditorががっつりRecordListに依存している
ColumnMenuだけばらそう
列の表示非表示を切り替えるやつ
22:57:32 できた。少しだけスッキリした
/icons/done.icon選択欄をcheck boxに直す
代わりに使っている<div>のCSSがURLの入力欄のデザインと衝突してしまうので、check boxに戻すことにした
React Tableで行を選択するとは違う方法でやっている影響で、選択表示が不完全になっている
→recorder-prototype#5fc827051280f000003a6086
直した
recorder-prototype#5fcb2c1d1280f00000930ab4
/icons/done.icon記録中のタイトルを変更した直後に完了ボタンを押すと、タイトルが消えてしまう現象を直した
firestoreへのデータ登録を非同期に行っていたのが原因だった
awaitを使って待つようにした
/icons/done.icon入力値をreal timeに反映する部分をhookに分離する
仕様
入力後一定時間経過すると登録された関数に入力値を送信する
setTimeoutを使う
外部からの入力値変更は、focusがあたっていないときのみ行う
useEffectを使う
外部の入力値の検証もやるか?
だが最初から不正な値を渡されると、正常な値として使えるものがなくなる
focusが外れたら直ちに入力値を送信する
検証機能付き
入力値が不正の場合は送信しない
入力値が不正な状態でfocusを外すと、初期値に戻す
18:27:53 Bulmaの.is-dangerが動くように、.textareaを入れた
min-heightに値が入って変なことになってしまうので、inline要素で無効に設定した
いろんなpropertyを無効にしなければ動きそうにないので止めた
代わりに.has-text-dangerで赤文字にするようにした
常にstart<endとなるよう入力値を検証する
endの代わりにdurationをdatabaseに格納しようかとも思ったが、data型の表現が面倒だな。やめよう。
recorder-prototypeに予定作成機能をつける
現在時刻を入力するショートカットがほしい
PCなら、keyboard shortcutを導入すれば良さそう
全deviceを視野に入れるなら、<input type='time'>とかを使ったほうが良いかも
/icons/doing.iconinputの代わりにdivを使う
11:45:50 断念。何故か固まってしまう
inputではなくtextareaを使うと良さそう
可変長<textarea>
19:16:04 できた
改善案
<textarea>の外枠をなくす
clickしたときのみ<textarea>を表示するようにする
/icons/doing.icon年月日の表示非表示を切り替えたい
headerに切り替えボタンをつけるか
2020-12-04 14:07:43 入れた
drop down menuの中にcheckboxを入れた
切り替えの状態は保存していない
これもdatabaseから読み込めるようにしておくといいかも
React Tableで列を隠す
キーボードショートカット
曖昧検索欄
入力すると記録名を曖昧検索して一覧表示する
fizzSearchを使う
実装
titleだけ取得して絞り込み検索を行うhookを作る
候補はどうやって表示すればいいかな?
これほしいな
井戸端編集で絞り込んで、どれだけ時間を費やしているのかとか知りたい
記録名置換
同じ名前の記録を一斉に別の名前へ変換する
リンク置換 (scrapbox)と同じ機能
実装
同じtitleの記録を全て検索して、一括置換する
置換する前に、置換するかどうかuserに聞く
簡易実行ボタン
各記録にボタンをつける
押すとその記録名で新たに記録を開始する
/icons/doing.iconofflineで実行できるようにする
Firestoreをofflineで使うを参考にする
2020-12-03 09:09:31 おかしい。multi-tabでも使えるoptionを有効にしたのにerrorがでる
FirebaseError
Failed to obtain exclusive access to the persistence layer. To allow shared access, multi-tab synchronization has to be enabled in all tabs. If you are using experimentalForceOwningTab:true, make sure that only one tab has persistence enabled at any given time.
09:13:55 option名が変わっていた。
変更後のoption名にしたら直った
きちんと動作している
networkを切断してもdataの読み書きができる
networkに復帰すると、dataが同期される
表示数を制限する
直近の20件のみ表示するようにしてみる
/icons/done.icon10:57:38 やった
絞り込みの都合上、一番上が最新の記録になるように変更した
逆に出来ないこともないが、こっちのほうが見やすそうなのでそのままにする
必要なデータだけを自動で取得・同期するようにしたい
テーブルには最大20件だけ表示して、ページめくりをするとその次の20件を読み込むようにするとか
カレンダーでも同じかな
どう実装するか
配列ではなくiteratorを返せば無限リストとして使える?
データ更新中であることを表示したい
データ更新用Hooksでもloadingとerrorを渡すようにする
もしくはPromiseを返す
これだとその場で読み込み中表示を作らないといけない
あんまり柔軟性ないかな?
Nav barにloginしたときだけ表示されるメニューを入れたい
入れたいもの
data exportボタン
2020-12-07 00:41:44 設計が難しいので一旦パス
authDataがundefinedのときの処理をuseExportに入れる必要が出てくるaa
予定やタイムラインへのリンク
どう実装するか
useAuthStateのuserだけつかう
user !== undefinedのときだけ表示するボタンにする
{authData && <>表示したい部品</>}を使う
/icons/done.icon先にuseAuthStateをHooks Injection patternで分離しておこう。
Login 中はLogin画面からdashboardにredirectするようにする
/icons/doing.iconScrapbox連携
行リンクを紐付ける
どこに記録を書いたか辿ることができる
リンクを登録するのがめんどくさそうtakker.icon
とりあえず登録欄だけでも作っておくか
field name: link
どう表示する?
そのまま表示すると場所を取る
普段は折りたたんで見えなくしておくとか
ふつうはdetailというリンクだけ出しておく
折りたたみを開くとURLの入力欄があわわれる
React Tableで行を折りたたむ
16:15:30 入力の反映は出来たが、何故かurlをtextareaに表示できない
property間違えている?
16:35:28 React Tableで設定したcolumnのidじゃないと行けないみたいだった
そっちにしたら直った
簡単に反映できるようにしたい
案
行リンクを選択した状態で特定のPageMenuを押すと記録が開始される
Scrapboxから起動できるように、APIを用意しておく
その他
ページを開いた状態でPageMenuかなにかを押すと、そのページのタイトルでコマがカレンダーに作成される
つまり1 clickで予定を作れるようにしたい
実装
cloud functionを使う必要があるな
どうやって実装すればいいのかはよく知らない
記録中でもURLを設定できるようにしたい
現状だと、記録後でないとURLを指定できない
自動読み込み
スクロールで自動読み込み?
一週間前の記録とかを見るのが大変
日付や週単位でpagenation?
こっちで見たいな
絞り込み検索の方が良いのでは?
裏で絞り込みのqueryを発行して、取得範囲を変えるようにしよう
frontendは、ボタンを使うなり検索formを使うなり好きにしてくれ
絞り込みをどちらでやる?
日付で絞り込み
databaseに任せたほうが良さそう
asearch
clientでやるしかないな
全dataを取得して、絞り込みをかける
重くならないか?
GitHubにexportする
流石にsandbox上で編集するのが限界に思えてきた
hot reloadしているから遅いし
firebase hostingにdeployする
PWA対応
React.jsでPWAを作る
#2020-12-07 00:10:06
#2020-12-06 10:01:47
#2020-12-04 13:52:48
#2020-12-03 03:07:17
#2020-12-02 21:47:52