e70267f738
Build & Deploy to K8s / build-and-deploy (push) Failing after 1m14s
- 음성 인식 (scada-demo/js/voice.js) — 한국어 발화 → 키워드 매핑 → INVYONE_UI.select() · 사이드바 마이크 버튼 + transcript 라벨, 매칭 시 청록 펄스 · Chrome/Edge HTTPS 환경 (운영 siflex.invyone.com OK) - 경고시스템/다중경고 버튼을 음성 인식과 동일 톤 · 🚨 emoji → SVG 삼각형 아이콘, voice-btn 패턴 (다크 솔리드 + 컬러 액센트) · 정적 (반짝 펄스 애니메이션 제거) - client.ts stash pop conflict 정리 (DEV_TENANT_HOST + 도메인 정리 통합) - ui.js 다중 경고 시연 wiring + scada 작업 노트 2건 - 기타 syncthing 보류분 batch (대시보드/레이아웃/로그인 layout 정리) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
119 lines
3.6 KiB
TypeScript
119 lines
3.6 KiB
TypeScript
import { create } from 'zustand';
|
|
import { devtools } from 'zustand/middleware';
|
|
|
|
interface DashEditTarget {
|
|
id: string;
|
|
name: string;
|
|
icon: string;
|
|
is_personal: boolean;
|
|
}
|
|
|
|
interface DashboardState {
|
|
dashboards: Record<string, any>[];
|
|
activeDashboardId: string | null;
|
|
cards: Record<string, any>[];
|
|
editMode: boolean;
|
|
loading: boolean;
|
|
createOpen: boolean;
|
|
/** 수정 모달 대상 — null 이면 모달 닫힘. CreateDashboardModal 을 mode='edit' 로 재사용. */
|
|
editTarget: DashEditTarget | null;
|
|
|
|
setDashboards: (dashboards: Record<string, any>[]) => void;
|
|
setActiveDashboard: (id: string | null) => void;
|
|
setCards: (cards: Record<string, any>[]) => void;
|
|
addCard: (card: Record<string, any>) => void;
|
|
updateCard: (cardId: string, updates: Record<string, any>) => void;
|
|
removeCard: (cardId: string) => void;
|
|
toggleEditMode: () => void;
|
|
setEditMode: (on: boolean) => void;
|
|
setLoading: (loading: boolean) => void;
|
|
addDashboard: (dashboard: Record<string, any>) => void;
|
|
updateDashboardInList: (id: string, updates: Record<string, any>) => void;
|
|
removeDashboard: (id: string) => void;
|
|
openCreate: () => void;
|
|
closeCreate: () => void;
|
|
openEdit: (target: DashEditTarget) => void;
|
|
closeEdit: () => void;
|
|
libOpen: boolean;
|
|
openLib: () => void;
|
|
closeLib: () => void;
|
|
}
|
|
|
|
export const useDashboardStore = create<DashboardState>()(
|
|
devtools(
|
|
(set) => ({
|
|
dashboards: [],
|
|
activeDashboardId: null,
|
|
cards: [],
|
|
editMode: false,
|
|
loading: false,
|
|
createOpen: false,
|
|
editTarget: null,
|
|
libOpen: false,
|
|
|
|
setDashboards: (dashboards) => set({ dashboards }),
|
|
|
|
setActiveDashboard: (id) =>
|
|
set((s) =>
|
|
s.activeDashboardId === id
|
|
? { activeDashboardId: id, editMode: false }
|
|
: { activeDashboardId: id, editMode: false, cards: [] }
|
|
),
|
|
|
|
setCards: (cards) => set({ cards }),
|
|
|
|
addCard: (card) => set((s) => ({ cards: [...s.cards, card] })),
|
|
|
|
updateCard: (cardId, updates) =>
|
|
set((s) => ({
|
|
cards: s.cards.map((c) =>
|
|
(c.card_id ?? c.CARD_ID) === cardId ? { ...c, ...updates } : c
|
|
),
|
|
})),
|
|
|
|
removeCard: (cardId) =>
|
|
set((s) => ({
|
|
cards: s.cards.filter((c) => (c.card_id ?? c.CARD_ID) !== cardId),
|
|
})),
|
|
|
|
toggleEditMode: () => set((s) => ({ editMode: !s.editMode })),
|
|
|
|
setEditMode: (on) => set({ editMode: on }),
|
|
|
|
setLoading: (loading) => set({ loading }),
|
|
|
|
addDashboard: (dashboard) =>
|
|
set((s) => ({ dashboards: [...s.dashboards, dashboard] })),
|
|
|
|
updateDashboardInList: (id, updates) =>
|
|
set((s) => ({
|
|
dashboards: s.dashboards.map((d) =>
|
|
(d.dashboard_id ?? d.DASHBOARD_ID) === id ? { ...d, ...updates } : d
|
|
),
|
|
})),
|
|
|
|
removeDashboard: (id) =>
|
|
set((s) => {
|
|
const filtered = s.dashboards.filter(
|
|
(d) => (d.dashboard_id ?? d.DASHBOARD_ID) !== id
|
|
);
|
|
const isActive = s.activeDashboardId === id;
|
|
return {
|
|
dashboards: filtered,
|
|
activeDashboardId: isActive
|
|
? (filtered[0]?.dashboard_id ?? filtered[0]?.DASHBOARD_ID ?? null)
|
|
: s.activeDashboardId,
|
|
};
|
|
}),
|
|
|
|
openCreate: () => set({ createOpen: true, editTarget: null }),
|
|
closeCreate: () => set({ createOpen: false }),
|
|
openEdit: (target) => set({ editTarget: target, createOpen: false }),
|
|
closeEdit: () => set({ editTarget: null }),
|
|
openLib: () => set({ libOpen: true }),
|
|
closeLib: () => set({ libOpen: false }),
|
|
}),
|
|
{ name: 'dashboard-store' }
|
|
)
|
|
);
|