Compare commits
3 Commits
b2a8f60cc0
...
7aa79f4a7d
| Author | SHA1 | Date |
|---|---|---|
|
|
7aa79f4a7d | |
|
|
b8b8cf9c52 | |
|
|
c4d7a1d787 |
|
|
@ -56,8 +56,9 @@ npm run deploy:dev # git push + scp + systemctl restart(git push だけでは
|
||||||
| ドキュメント | 内容 |
|
| ドキュメント | 内容 |
|
||||||
|-------------|------|
|
|-------------|------|
|
||||||
| `STATUS.md` | **今何をしている最中か(毎セッション参照・更新)** |
|
| `STATUS.md` | **今何をしている最中か(毎セッション参照・更新)** |
|
||||||
|
| `DESIGN.md` | **UI 生成時はここの値のみ使うこと。色・クラス名・アイコン・spacing の正** |
|
||||||
| `docs/master-architecture.md` | インフラ構成・全アプリ一覧・URL |
|
| `docs/master-architecture.md` | インフラ構成・全アプリ一覧・URL |
|
||||||
| `docs/design-system.md` | カラートークン・デザインシステム |
|
| `docs/design-system.md` | カラートークン詳細(DESIGN.md の補足) |
|
||||||
| `docs/new-app-guide.md` | 新規アプリ作成チェックリスト |
|
| `docs/new-app-guide.md` | 新規アプリ作成チェックリスト |
|
||||||
| `docs/disaster-recovery.md` | PC 消失時の復元手順 |
|
| `docs/disaster-recovery.md` | PC 消失時の復元手順 |
|
||||||
| `docs/server-refactor-plan.md` | server.js 分割設計・実施タイミング・手順 |
|
| `docs/server-refactor-plan.md` | server.js 分割設計・実施タイミング・手順 |
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,9 @@ npm run deploy:dev # git push + scp + systemctl restart(git push だけでは
|
||||||
| ドキュメント | 内容 |
|
| ドキュメント | 内容 |
|
||||||
|-------------|------|
|
|-------------|------|
|
||||||
| `STATUS.md` | **今何をしている最中か(毎セッション参照・更新)** |
|
| `STATUS.md` | **今何をしている最中か(毎セッション参照・更新)** |
|
||||||
|
| `DESIGN.md` | **UI 生成時はここの値のみ使うこと。色・クラス名・アイコン・spacing の正** |
|
||||||
| `docs/master-architecture.md` | インフラ構成・全アプリ一覧・URL |
|
| `docs/master-architecture.md` | インフラ構成・全アプリ一覧・URL |
|
||||||
| `docs/design-system.md` | カラートークン・デザインシステム |
|
| `docs/design-system.md` | カラートークン詳細(DESIGN.md の補足) |
|
||||||
| `docs/new-app-guide.md` | 新規アプリ作成チェックリスト |
|
| `docs/new-app-guide.md` | 新規アプリ作成チェックリスト |
|
||||||
| `docs/disaster-recovery.md` | PC 消失時の復元手順 |
|
| `docs/disaster-recovery.md` | PC 消失時の復元手順 |
|
||||||
| `docs/server-refactor-plan.md` | server.js 分割設計・実施タイミング・手順 |
|
| `docs/server-refactor-plan.md` | server.js 分割設計・実施タイミング・手順 |
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,323 @@
|
||||||
|
# DESIGN.md — Posimai Design System
|
||||||
|
|
||||||
|
> CSS 変数・コンポーネントクラスの「正」は `posimai-ui/public/v1/base.css`(Vercel: https://posimai-ui.vercel.app/v1/base.css)。
|
||||||
|
> このファイルはその **意図・制約・使い分けのルール** を記述する。値を変更する場合は base.css を先に更新し、このファイルをそれに合わせること。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 適用外アプリ(冒頭必読)
|
||||||
|
|
||||||
|
以下のアプリには **このデザインシステムを適用しない**。専用テーマを持つ。
|
||||||
|
|
||||||
|
| アプリ | 理由 |
|
||||||
|
|--------|------|
|
||||||
|
| `ponshu-room` / `ponshu_room_lite` | 独自テーマ(和紙 x 墨 x 琥珀)。Posimai デザインシステム適用外 |
|
||||||
|
| `posimai-analytics` | BtoB ダッシュボード。TailwindCSS + React + ライトテーマで構築 |
|
||||||
|
|
||||||
|
## `docs/design-system.md` との関係
|
||||||
|
|
||||||
|
`docs/design-system.md` は **このファイルの補足・詳細版**として残存しているが、**AI が参照する正はこの DESIGN.md のみ**。二重参照した場合はこのファイルを優先すること。`docs/design-system.md` は将来的に廃止または統合予定。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. ビジュアルテーマと雰囲気
|
||||||
|
|
||||||
|
「静かな深夜のオフィス。teal はモニターの中に 1 か所だけ灯る光」
|
||||||
|
|
||||||
|
- **ベーストーン**: ディープブラック。派手さではなく「奥行き」を出す
|
||||||
|
- **アクセント**: teal は画面全体の 1 割以下。CTA・アクティブ状態・データポイントのみに使う
|
||||||
|
- **静けさ優先**: neutral が 9 割を占めることで、teal が際立つ
|
||||||
|
- **日本語 UI**: 文字は小さく・weight は控えめに。ダッシュボード密度に耐える読みやすさ
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. カラーパレットと役割
|
||||||
|
|
||||||
|
### ダークテーマ(デフォルト)
|
||||||
|
|
||||||
|
```css
|
||||||
|
--bg: #0D0D0D /* ページ背景 */
|
||||||
|
--surface: #1A1A1A /* カード・パネル面 */
|
||||||
|
--surface2: #252525 /* ネスト面・入力フィールド背景 */
|
||||||
|
--border: #2D2D2D /* ボーダー・区切り線 */
|
||||||
|
--text: #F3F4F6 /* 主テキスト */
|
||||||
|
--text2: #9CA3AF /* 副テキスト・ラベル */
|
||||||
|
--text3: #6B7280 /* 弱テキスト・プレースホルダー */
|
||||||
|
--accent: #6EE7B7 /* Posimai Teal — CTA・アクティブ状態のみ */
|
||||||
|
--accent-dim: rgba(110,231,183,0.1) /* アクティブ背景 */
|
||||||
|
--accent-border: rgba(110,231,183,0.25) /* アクティブボーダー */
|
||||||
|
|
||||||
|
/* 角丸 */
|
||||||
|
--radius: 12px /* カード・モーダル等 */
|
||||||
|
--radius-sm: 8px /* ボタン・インプット等 */
|
||||||
|
```
|
||||||
|
|
||||||
|
### ライトテーマ(`[data-theme="light"]`)
|
||||||
|
|
||||||
|
```css
|
||||||
|
--bg: #F9FAFB
|
||||||
|
--surface: #FFFFFF
|
||||||
|
--accent: #059669 /* ライト時はより深い green に自動切替 */
|
||||||
|
```
|
||||||
|
|
||||||
|
### アプリ別アクセント(特例)
|
||||||
|
|
||||||
|
特例上書きは `[data-app-id]` セレクタで行う。`:root` や `body` への上書きは禁止。
|
||||||
|
|
||||||
|
```css
|
||||||
|
/* OK: アプリ固有の上書きパターン */
|
||||||
|
[data-app-id="posimai-atlas"] { --accent: #22D3EE; } /* Cyan */
|
||||||
|
[data-app-id="posimai-dev"] { --accent: #A78BFA; } /* Violet */
|
||||||
|
[data-app-id="posimai-journal"]{ --accent: #80CAEE; } /* Sky-Blue */
|
||||||
|
|
||||||
|
/* NG: ルートへの直書き上書き */
|
||||||
|
:root { --accent: #22D3EE; }
|
||||||
|
```
|
||||||
|
|
||||||
|
| アプリ | ダーク accent | 理由 |
|
||||||
|
|--------|-------------|------|
|
||||||
|
| 全般(デフォルト) | `#6EE7B7` Teal | Posimai ブランドカラー |
|
||||||
|
| posimai-journal / posimai-site | `#80CAEE` Sky-Blue | 静かで知的な印象 |
|
||||||
|
| posimai-atlas | `#22D3EE` Cyan | サイバー・ターミナル感。背景も `#0C1221` navy |
|
||||||
|
| posimai-dev | `#A78BFA` Violet | コード・AI・ターミナルの融合 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. タイポグラフィ
|
||||||
|
|
||||||
|
**現行**: Geist(v1/base.css で定義済み)
|
||||||
|
**移行予定**: フォントを別途比較検討中。決定後に base.css v2 でオプトイン移行。一斉変更はしない。
|
||||||
|
|
||||||
|
### 基本ルール
|
||||||
|
|
||||||
|
- **フォントサイズ**: `14px` ベース。`11px` / `12px` / `13px` / `14px` / `15px` の5段階
|
||||||
|
- **フォントウェイト**: 300 / 400 / 500 / 600 の4段階(700 は原則使わない)
|
||||||
|
- **letter-spacing**: ヘッダー・ブランド名には `-0.01em`、ラベル大文字には `0.08em`
|
||||||
|
- **行間**: `1.6`(本文)
|
||||||
|
- **日本語**: Noto Sans JP を補助フォントとして追加予定(font-family フォールバックに含める)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. アイコン
|
||||||
|
|
||||||
|
**使用ライブラリ**: Lucide `@0.344.0` 固定(バージョン変更禁止)
|
||||||
|
|
||||||
|
### サイズ標準(3段階)
|
||||||
|
|
||||||
|
| 用途 | サイズ |
|
||||||
|
|------|--------|
|
||||||
|
| テキスト横・バッジ内 | 16px |
|
||||||
|
| ボタン内・リストアイテム | 20px |
|
||||||
|
| 空状態・大きな CTA | 24px |
|
||||||
|
|
||||||
|
### stroke-width ルール
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- OK: stroke-width は 1.5 に統一 -->
|
||||||
|
<i data-lucide="star" style="width:20px;height:20px;stroke-width:1.5"></i>
|
||||||
|
|
||||||
|
<!-- NG: stroke-width 2.0 以上は使わない(太く見える) -->
|
||||||
|
<i data-lucide="star" style="width:20px;height:20px;stroke-width:2"></i>
|
||||||
|
```
|
||||||
|
|
||||||
|
- fill アイコン(play / heart 等を塗りつぶす場合)は `fill:currentColor; stroke:none`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. コンポーネントスタイル
|
||||||
|
|
||||||
|
### クラス名対応表
|
||||||
|
|
||||||
|
| 用途 | クラス名 | 備考 |
|
||||||
|
|------|---------|------|
|
||||||
|
| カード | `.card` | base.css 定義。全 HTML アプリで使用可 |
|
||||||
|
| ガラスパネル | `.glass-panel` | posimai-dashboard 専用(Tailwind / Next.js)。HTML アプリでは `.card` を使うこと |
|
||||||
|
| ガラスパネル(ホバー) | `.glass-panel-interactive` | posimai-dashboard 専用 |
|
||||||
|
| モーダル本体 | `.modal` | base.css 定義 |
|
||||||
|
| モーダル背景 | `.modal-overlay` / `.overlay` | base.css 定義 |
|
||||||
|
| CTA ボタン(teal) | `.btn.btn-primary` | base.css 定義 |
|
||||||
|
| セカンダリボタン | `.btn.btn-ghost` | base.css 定義 |
|
||||||
|
| アイコンボタン | `.icon-btn` | base.css 定義 |
|
||||||
|
| ヘッダー | `.header` | base.css 定義 |
|
||||||
|
| サイドバー | `.sidebar` | base.css 定義 |
|
||||||
|
| ナビアイテム | `.nav-item`(アクティブ: `.nav-item.active`)| base.css 定義 |
|
||||||
|
| セクションラベル | `.section-label` | base.css 定義 |
|
||||||
|
| トースト通知 | `#toast`(`.show` で表示)| base.css 定義 |
|
||||||
|
|
||||||
|
### カード
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- OK: .card クラスを使う -->
|
||||||
|
<div class="card">...</div>
|
||||||
|
|
||||||
|
<!-- NG: インラインでスタイルを再定義 -->
|
||||||
|
<div style="background:#1A1A1A;border:1px solid #2D2D2D;border-radius:12px;padding:16px">...</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
`.card` の定義: `background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px`
|
||||||
|
|
||||||
|
### ボタン
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- CTA: teal を使ってよい唯一のボタン -->
|
||||||
|
<button class="btn btn-primary">保存</button>
|
||||||
|
|
||||||
|
<!-- セカンダリ: teal を使わない -->
|
||||||
|
<button class="btn btn-ghost">キャンセル</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 空状態(Empty State)
|
||||||
|
|
||||||
|
空のコンテナを表示することは禁止。必ずアイコン + 説明テキストを実装する。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- OK -->
|
||||||
|
<div class="empty-state">
|
||||||
|
<i data-lucide="inbox" style="width:24px;height:24px;stroke-width:1.5"></i>
|
||||||
|
<p>まだデータがありません</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- NG: 空のコンテナを表示 -->
|
||||||
|
<div class="list"></div>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. レイアウト原則
|
||||||
|
|
||||||
|
### Spacing Scale(月例会議ダッシュボード準拠)
|
||||||
|
|
||||||
|
| トークン | 値 | 用途 |
|
||||||
|
|---------|-----|------|
|
||||||
|
| xs | 8px | ラベル-値間・アイコン-テキスト間 |
|
||||||
|
| sm | 10px | ボタン内 padding(縦)・リストアイテム間 |
|
||||||
|
| md | 14px | カード内要素間 |
|
||||||
|
| lg | 20px | カード内 padding |
|
||||||
|
| xl | 28px | セクション間・グループ間 |
|
||||||
|
|
||||||
|
### グリッド・最大幅
|
||||||
|
|
||||||
|
- **単一カラム(モバイル中心、HTML アプリ)**: `max-width: 860px`
|
||||||
|
- **サイドバーあり(HTML アプリ)**: `max-width: 1100px`(コンテンツ部分)
|
||||||
|
- **サイドバーあり(posimai-dashboard / Next.js)**: `max-width: 1400px`(`DashboardShell.tsx` の実装値)
|
||||||
|
- **ボトムパディング**: `calc(40px + env(safe-area-inset-bottom))` で iPhone ホームインジケーター対応
|
||||||
|
|
||||||
|
### ヘッダー
|
||||||
|
|
||||||
|
- 高さ: `52px`(`--header-h`)固定
|
||||||
|
- sticky + backdrop-blur: `backdrop-filter: blur(16px)`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 深さと段階
|
||||||
|
|
||||||
|
### シャドウ
|
||||||
|
|
||||||
|
```css
|
||||||
|
--shadow-sm: 0 2px 8px rgba(0,0,0,0.3) /* カード・小要素 */
|
||||||
|
--shadow-lg: 0 8px 32px rgba(0,0,0,0.5) /* モーダル・サイドバー */
|
||||||
|
```
|
||||||
|
|
||||||
|
### トランジション(base.css 定義値)
|
||||||
|
|
||||||
|
```css
|
||||||
|
--ease: cubic-bezier(.4, 0, .2, 1) /* 標準イージング */
|
||||||
|
--dur: 0.2s /* 標準時間 */
|
||||||
|
```
|
||||||
|
|
||||||
|
インタラクティブ要素のトランジションは `transition: all var(--dur) var(--ease)` を使うこと。
|
||||||
|
|
||||||
|
### グラデーション・エフェクトの使用範囲
|
||||||
|
|
||||||
|
```
|
||||||
|
禁止: ページ・カードの背景色をグラデーションにする
|
||||||
|
box-shadow: 0 0 20px var(--accent) のような全面グロー
|
||||||
|
|
||||||
|
許可: ブランドロゴ内のグラデーション(.brand-logo の linear-gradient)
|
||||||
|
アプリの演出エフェクト(aurora blob 等)— ただし以下の条件を満たす場合のみ
|
||||||
|
- pointer-events: none で操作を邪魔しない
|
||||||
|
- opacity / blur で主コンテンツより必ず背景に収まる
|
||||||
|
- posimai-dev / posimai-atlas 等サイバー系アプリに限定
|
||||||
|
- 一般的な情報・ツール系アプリには使わない
|
||||||
|
```
|
||||||
|
|
||||||
|
### 重なり順(z-index)
|
||||||
|
|
||||||
|
| 層 | z-index | 用途 |
|
||||||
|
|----|---------|------|
|
||||||
|
| 通常コンテンツ | 0〜99 | カード・リスト |
|
||||||
|
| ヘッダー | 100 | sticky header |
|
||||||
|
| オーバーレイ | 150 | モーダル背景 |
|
||||||
|
| サイドバー | 200 | ナビ |
|
||||||
|
| 設定パネル | 300 | 設定スライドイン |
|
||||||
|
| トースト | 9999 | 通知 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. レスポンシブ動作
|
||||||
|
|
||||||
|
- **ブレークポイント**: `1024px`(PC サイドバー常時表示 / モバイルはドロワー)
|
||||||
|
- **モバイルファースト**: スタイルはモバイルを基準に書き、`@media (min-width: 1024px)` で上書き
|
||||||
|
- **タッチターゲット**: ボタン・アイコンボタンの最小サイズは `44px x 44px`
|
||||||
|
- **外部リンク**: 必ず `target="_blank" rel="noopener"` をセットで付ける
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Do's and Don'ts(コードレベル)
|
||||||
|
|
||||||
|
### 色の使い方
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- NG: トークン外の色をインラインで直書き -->
|
||||||
|
<div style="color: #6EE7B7">テキスト</div>
|
||||||
|
<div style="background: #1A1A1A">カード</div>
|
||||||
|
|
||||||
|
<!-- OK: CSS 変数を使う -->
|
||||||
|
<div style="color: var(--accent)">テキスト</div>
|
||||||
|
<div class="card">カード</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### teal(accent)の使い方
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- NG: teal を装飾・テキスト・ボーダーに多用 -->
|
||||||
|
<h2 style="color: var(--accent)">セクションタイトル</h2>
|
||||||
|
<div style="border: 1px solid var(--accent)">通常カード</div>
|
||||||
|
|
||||||
|
<!-- OK: CTA・アクティブ状態・データポイントのみ -->
|
||||||
|
<button class="btn btn-primary">保存</button>
|
||||||
|
<div class="nav-item active">アクティブなナビ</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### アイコン
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- NG: stroke-width 2 以上、サイズが標準外 -->
|
||||||
|
<i data-lucide="check" style="width:18px;height:18px;stroke-width:2.5"></i>
|
||||||
|
|
||||||
|
<!-- OK: stroke-width 1.5、標準サイズ -->
|
||||||
|
<i data-lucide="check" style="width:16px;height:16px;stroke-width:1.5"></i>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 絵文字
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- NG: 絵文字をコード・UI・コメントに使う -->
|
||||||
|
<span>✅ 完了</span>
|
||||||
|
|
||||||
|
<!-- OK: テキストのみ -->
|
||||||
|
<span>完了</span>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. AI 向けプロンプトガイド
|
||||||
|
|
||||||
|
**Cursor・Claude Code・その他 AI エージェントへ**
|
||||||
|
|
||||||
|
1. UI を生成・修正するとき、色・フォント・サイズ・クラス名はすべてこのファイルの値のみ使うこと
|
||||||
|
2. `ponshu-room` / `ponshu_room_lite` / `posimai-analytics` にはこのシステムを適用しないこと
|
||||||
|
3. CSS 変数の値を変更する場合は `posimai-ui/public/v1/base.css` を更新してからこのファイルを修正すること(逆順禁止)
|
||||||
|
4. フォントはまだ移行検討中。現行の Geist を変更しないこと。変更指示があるまで待機すること
|
||||||
|
5. クラス名が対応表にある場合は必ずそのクラスを使い、インラインで再定義しないこと
|
||||||
|
6. 新規アプリのアクセント色を変える場合は `[data-app-id="アプリ名"]` セレクタで上書きし、`:root` を書き換えないこと
|
||||||
|
|
@ -391,7 +391,7 @@ function updateRing(fillId,valId,pct,circ,base,warn,crit){
|
||||||
fill.style.strokeDashoffset=circ*(1-Math.min(pct,100)/100);
|
fill.style.strokeDashoffset=circ*(1-Math.min(pct,100)/100);
|
||||||
const color=pct>80?(crit||'#F87171'):pct>60?(warn||'#FB923C'):(base||'#22D3EE');
|
const color=pct>80?(crit||'#F87171'):pct>60?(warn||'#FB923C'):(base||'#22D3EE');
|
||||||
fill.style.stroke=color;
|
fill.style.stroke=color;
|
||||||
valEl.textContent=pct>0?`${pct}%`:'—';
|
valEl.textContent=`${pct}%`;
|
||||||
valEl.style.fill=pct>80?'#F87171':pct>60?'#FB923C':'var(--text)';
|
valEl.style.fill=pct>80?'#F87171':pct>60?'#FB923C':'var(--text)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -762,6 +762,11 @@ function buildRouter() {
|
||||||
const p = df.trim().split('\n')[1].split(/\s+/);
|
const p = df.trim().split('\n')[1].split(/\s+/);
|
||||||
disk = { total_gb: Math.round(parseInt(p[1])/1e9*10)/10, used_gb: Math.round(parseInt(p[2])/1e9*10)/10, use_pct: Math.round(parseInt(p[2])/parseInt(p[1])*100) };
|
disk = { total_gb: Math.round(parseInt(p[1])/1e9*10)/10, used_gb: Math.round(parseInt(p[2])/1e9*10)/10, use_pct: Math.round(parseInt(p[2])/parseInt(p[1])*100) };
|
||||||
} catch(_) {}
|
} catch(_) {}
|
||||||
|
let users = 0;
|
||||||
|
try {
|
||||||
|
const whoOut = execSync('who 2>/dev/null', { timeout: 1000 }).toString().trim();
|
||||||
|
users = whoOut ? whoOut.split('\n').filter(l => l.trim()).length : 0;
|
||||||
|
} catch(_) {}
|
||||||
res.json({
|
res.json({
|
||||||
...base,
|
...base,
|
||||||
gemini: !!genAI,
|
gemini: !!genAI,
|
||||||
|
|
@ -770,6 +775,8 @@ function buildRouter() {
|
||||||
mem_used_mb: Math.round((total - mem) / 1024 / 1024),
|
mem_used_mb: Math.round((total - mem) / 1024 / 1024),
|
||||||
mem_total_mb: Math.round(total / 1024 / 1024),
|
mem_total_mb: Math.round(total / 1024 / 1024),
|
||||||
disk,
|
disk,
|
||||||
|
users,
|
||||||
|
node_version: process.version,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue