TimeGridは、複数ユーザーがリアルタイムで共同編集できるタイムスケジュール管理ウェブアプリケーションです。 イベント運営、学園祭、会議進行、シフト管理など、時間と場所(ステージ・部屋など)の軸を持つ予定を グリッド形式で視覚的に管理できます。
- 🗂 グリッドベースの編集: 時間(縦軸)× 場所(横軸)の直感的なUI
- 🖱 ドラッグ&ドロップ: 予定の移動・時間伸縮・列間移動が可能
- 👥 共同編集(リアルタイム同期): 他のユーザーの変更が数秒で自動反映されます
- 📍 場所のカスタマイズ: 列の追加・並び替え・色変更が可能(複数場所にまたがる予定も可)
- ⚡ タスクと期間: 時間幅のある「期間」イベントと、開始時刻のみの「タスク」マーカーを使い分け
- 📱 PWA対応 / タッチ最適化: ホーム画面にインストールしてオフライン閲覧も可能。スマホでは空きマスをタップで予定作成、ボトムシートUI、セーフエリア対応で快適に操作できます
- 📝 備考列 / 自動テキストカラー / 時計ライン / 印刷対応 / JSONエクスポート
- ⌨️ キーボードショートカット:
N=新規,Esc=閉じる,Ctrl+P=印刷, 予定編集中Ctrl/Cmd+Enter=保存
ピュアな静的+PHPアーキテクチャ。Node.js 等のプロセス常駐型サーバーは不要です。
| レイヤー | 技術 |
|---|---|
| フロントエンド | Vanilla JavaScript (ES2020) / CSS3 / HTML5 |
| バックエンド | 単一ファイルの PHP API (api.php) |
| データストレージ | ファイルベース JSON (排他ロック付き) |
| リアルタイム同期 | 変更ログのロングポーリング (?action=changes&since=...) |
| オフライン対応 | Service Worker + Web App Manifest |
PHP 7.4+ が動く 共有ホスティング(cloudfree.jp 等)にそのままアップロード するだけで動作します。
public/
├── index.html # アプリシェル
├── api.php # 単一ファイルのバックエンドAPI
├── manifest.webmanifest # PWA manifest
├── sw.js # Service Worker
├── .htaccess # Apache 設定(MIME / セキュリティヘッダ / 期限)
├── css/style.css
├── js/
│ ├── api.js # API クライアント + ポーリングシンク
│ ├── state.js # アプリ内ステート
│ ├── timeline.js # タイムラインレンダラ
│ ├── events.js # イベント CRUD / D&D / リサイズ
│ └── app.js # ルーティング / モーダル / PWA 登録
├── icons/ # PWAアイコン(SVG + PNG)
└── data/ # サーバー書き込み先(本番では自動生成)
└── .htaccess # 直接アクセス禁止
# PHP 7.4+ がインストールされていれば組み込みサーバーで起動できます
php -S localhost:8080 -t publicブラウザで http://localhost:8080/ を開いてください。
public/配下のファイルを FTP/SFTP でサーバーの公開ディレクトリにアップロード- サーバーで
public/data/ディレクトリに書き込み権限があることを確認(通常755/775) - ブラウザでアクセス → 自動的に
data/db.jsonとdata/changes.jsonが生成されます
ℹ️ このリポジトリには GitHub Actions による FTP自動デプロイ が設定されています(
.github/workflows/deploy.yml)。mainブランチへの push で自動反映されます。
| ファイル | 役割 |
|---|---|
data/db.json |
全スケジュール / 場所 / 予定のデータ |
data/changes.json |
変更ログ(最新500件まで自動トリム) |
data/db.lock |
書き込み時の排他ロック |
data/ 内の .htaccess により、これらのファイルは直接ダウンロードできません。
.htaccessでX-Content-Type-Options,X-Frame-Options,Referrer-Policy等のセキュリティヘッダを付与- すべてのユーザー入力はサーバー側で型・長さ・カラーコード形式をバリデーション
place_idsは該当スケジュールに属する場所 ID のみ受理- データファイル (
db.json等) は.htaccessにより直接アクセス不可 - XSS 対策: フロントエンドは
textContent/escHtml()で挿入
モダンブラウザ(Chrome, Edge, Firefox, Safari, iOS Safari)。Service Worker は HTTPS(または localhost)で有効化されます。
- スクロールで「時間」「場所」が消える問題を修正
タイムライングリッドの
overflow: hiddenがposition: stickyの固定対象(スクロール領域)を妨げており、さらに.place-headerのposition: relativeがヘッダーの sticky 指定を上書きしていました。両方を修正し、左の時間列と**上の場所ヘッダー(左上の角を含む)**が縦横スクロール時も常に固定表示されるようにしました。 - 複数場所にまたがるタスク/予定の描画バグを修正 以前は列ごとにブロックを生成し、ピン(タスクアイコン)は全列に出るのにタイトルは1つだけ、という不整合がありました。連続する場所は1つの横長ブロックにまとめ(ピン・タイトルとも1回だけ表示)、非連続の場所(例: 場所1と場所3)はそれぞれ独立したラベル付きブロックとして表示するように作り直しました。
- 予定とタスク/予定同士が時間で重なる時の表示崩れを修正 同じ場所・同じ時間帯に複数の予定(例: 10:00 のタスクと 10:00〜 の予定)があると重なって読めなくなっていました。重なりを検出して**横に並べて(レーン分割)**表示するようにし、すべての予定が見えるようにしました。
- 時間・場所の固定を切り替えるボタンを追加
ツールバーのピンボタンで固定(sticky)の ON/OFF を切り替えられます。大きな画面で全体を自由にスクロールしたい場合に解除できます。設定は
localStorageに保存され、次回も維持されます。 - モバイルでの固定ヘッダーをコンパクト化 固定部分が画面の大半を占めないよう、スマホではヘッダーの高さ・余白・文字サイズを縮小しました。
PC前提だった操作系を見直し、スマートフォン(特に iOS のホーム画面 PWA)でも快適に使えるよう細部を作り込みました。
- PWAで場所名・タイトルが隠れる問題を修正
iOS でホーム画面に追加(standalone 表示)した際、ステータスバー/ノッチの下にヘッダーが潜り込み、スケジュール名や場所名が半分隠れていました。
env(safe-area-inset-*)(セーフエリア)を全てのバー・モーダル・トースト・オフライン表示に適用し、ノッチや角丸・ホームインジケータを避けて表示するようにしました。 - エディタ本体の高さ計算を修正
ヘッダー高さをハードコード(
calc(100vh - 57px)等)していたため、セーフエリア適用後に下端が見切れていました。Flexbox レイアウト+100dvh(dynamic viewport height)に変更し、モバイル Safari のアドレスバー伸縮にも追従するようにしました。 - 長い場所名の見切れを修正
ヘッダーの場所名を最大2行で折り返し表示し、
title属性で全文ツールチップも表示するようにしました。 - タイトル入力中の Enter で予定が保存されてしまう問題を修正 「タイトル → 場所 → 時間」と入力していく途中で Enter を押しても保存されないようにしました(後述)。
- 予定編集フォームの Enter 挙動を刷新
- タイトル欄で Enter → 保存ではなく「開始時刻」へフォーカス移動(次のステップへ自然に誘導)。
- 各入力欄で Enter → 次の入力欄へ移動。誤って保存されることはありません。
- 保存は 保存ボタン、または Ctrl/Cmd + Enter のショートカットで明示的に行います。
- タッチ操作の最適化
- 空きマスを タップするだけ で予定を作成可能に(PCのダブルクリックも継続サポート)。
- 予定ブロックを縦になぞるだけでは移動せず、明確にドラッグした時だけ移動する判定に変更(スクロールとドラッグの誤爆を防止)。
- リサイズハンドル・色ピッカー・チェックボックス・アイコンボタンなど、タップ対象を指で押しやすいサイズに拡大。
- タッチ端末では hover が無いため、各予定の「編集」ボタンを常時表示。
- 時間列の固定表示(横スクロール追従) 横スクロールしても左端の時間列が常に見えるよう sticky 化。狭い画面で「今どの時間か」を見失いません。
- モバイルではモーダルをボトムシート化 画面下から立ち上がる UI に変更し、保存ボタンを常に親指の届く位置に固定。
- iOS の入力ズーム抑制 入力欄のフォントを 16px 以上に調整し、フォーカス時の自動ズーム(レイアウトずれの原因)を防止。
- 終了時刻の自動補正 開始時刻を変更した際、終了時刻が開始以前になっていたら自動で「開始 +1時間」に補正。途中のバリデーションエラーを軽減。
- 入力長の上限表示
各入力欄にサーバー側と同じ
maxlengthを設定し、サイレントな切り詰めを防止。 - PWA の自動更新 Service Worker のバージョンを更新。新しいアセットが配信されたら自動で1回リロードし、常に最新 UI を表示します。
MIT