feat: complete legacy UI and playout parity migration
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,8 @@
|
||||
<section class="left-panel" aria-label="종목 및 컷 선택">
|
||||
<header class="brand-line">
|
||||
<div class="brand"><span>매일경제TV</span><strong>VRi</strong></div>
|
||||
<div class="connection-state" aria-label="Tornado2 연결 상태">미연결</div>
|
||||
<div class="connection-state" id="playout-connection-state"
|
||||
aria-label="Tornado2 연결 상태">미연결</div>
|
||||
</header>
|
||||
|
||||
<div class="search-line">
|
||||
@@ -23,10 +24,16 @@
|
||||
<div id="stock-results" class="stock-results" role="listbox" aria-label="종목명"></div>
|
||||
|
||||
<div class="manual-actions" aria-label="수동 입력">
|
||||
<button type="button" disabled>주요매출 구성</button>
|
||||
<button type="button" disabled>성장성 지표</button>
|
||||
<button type="button" disabled>매출액</button>
|
||||
<button type="button" disabled>영업이익</button>
|
||||
<button type="button" data-manual-screen="revenue-composition">주요매출 구성</button>
|
||||
<button type="button" data-manual-screen="growth-metrics">성장성 지표</button>
|
||||
<button type="button" data-manual-screen="sales">매출액</button>
|
||||
<button type="button" data-manual-screen="operating-profit">영업이익</button>
|
||||
</div>
|
||||
<div class="manual-list-actions" aria-label="수동 송출 목록" hidden>
|
||||
<button type="button" data-manual-list-screen="individual">개인 순매도</button>
|
||||
<button type="button" data-manual-list-screen="foreign">외국인 순매도</button>
|
||||
<button type="button" data-manual-list-screen="institution">기관 순매도</button>
|
||||
<button type="button" data-manual-list-screen="vi">VI 발동</button>
|
||||
</div>
|
||||
|
||||
<div id="cut-list" class="cut-list" role="listbox" aria-label="종목 컷" aria-multiselectable="true"></div>
|
||||
@@ -34,74 +41,195 @@
|
||||
</section>
|
||||
|
||||
<section class="catalog-panel" aria-label="분류별 그래픽">
|
||||
<nav class="market-tabs" aria-label="시장 분류">
|
||||
<button class="active" type="button" disabled>해외</button>
|
||||
<button type="button" disabled>환율</button>
|
||||
<button type="button" disabled>지수</button>
|
||||
<button type="button" disabled>코스피</button>
|
||||
<button type="button" disabled>코스닥</button>
|
||||
<button type="button" disabled>비교</button>
|
||||
<button type="button" disabled>테마</button>
|
||||
<button type="button" disabled>해외종목</button>
|
||||
<button type="button" disabled>전문가</button>
|
||||
<button type="button" disabled>정지</button>
|
||||
<nav id="market-tabs" class="market-tabs" aria-label="시장 분류">
|
||||
<button class="active" type="button" draggable="true" data-tab-id="overseas">해외</button>
|
||||
<button type="button" draggable="true" data-tab-id="exchange">환율</button>
|
||||
<button type="button" draggable="true" data-tab-id="index">지수</button>
|
||||
<button type="button" draggable="true" data-tab-id="kospiIndustry">코스피</button>
|
||||
<button type="button" draggable="true" data-tab-id="kosdaqIndustry">코스닥</button>
|
||||
<button type="button" draggable="true" data-tab-id="comparison">비교</button>
|
||||
<button type="button" draggable="true" data-tab-id="theme">테마</button>
|
||||
<button type="button" draggable="true" data-tab-id="overseasStocks">해외종목</button>
|
||||
<button type="button" draggable="true" data-tab-id="expert">전문가</button>
|
||||
<button type="button" draggable="true" data-tab-id="tradingHalt">정지</button>
|
||||
</nav>
|
||||
<label class="expand-line"><input type="checkbox" checked disabled> Expand</label>
|
||||
<label class="expand-line"><input id="catalog-expand-all" type="checkbox" checked> Expand</label>
|
||||
<div class="category-title">Category</div>
|
||||
<div class="category-tree" aria-label="원본 카테고리">
|
||||
<div class="tree-root">⊖ <strong>[1열판기본]</strong></div>
|
||||
<div class="tree-item">▸ 다우</div>
|
||||
<div class="tree-item">▸ 나스닥</div>
|
||||
<div class="tree-item">▸ S&P</div>
|
||||
<div class="tree-item">▸ 독일</div>
|
||||
<div class="tree-item">▸ 영국</div>
|
||||
<div class="tree-item">▸ 프랑스</div>
|
||||
<div class="tree-item">▸ 니케이</div>
|
||||
<div class="tree-item">▸ 중국 상해</div>
|
||||
<div class="tree-item">▸ 홍콩 항셍</div>
|
||||
<div class="tree-item">▸ 대만 가권</div>
|
||||
<div class="tree-item">▸ 싱가포르 지수</div>
|
||||
<div class="tree-item">▸ 필리핀 지수</div>
|
||||
<div class="tree-item">▸ 말레이시아 지수</div>
|
||||
<div class="tree-root second">⊖ <strong>[2열판-]</strong></div>
|
||||
<div class="tree-item">▸ 공산품 [원면, 목화(면화)]</div>
|
||||
<div class="tree-item">▸ 원자재 [국제 금, 국제 은]</div>
|
||||
</div>
|
||||
<div id="category-tree" class="category-tree" aria-label="원본 카테고리"></div>
|
||||
</section>
|
||||
|
||||
<section class="playlist-panel" aria-label="플레이리스트">
|
||||
<div class="playlist-toolbar">
|
||||
<label><input type="checkbox" checked disabled> 전체</label>
|
||||
<label><input type="checkbox" checked disabled> 5일선</label>
|
||||
<label><input type="checkbox" checked disabled> 20일선</label>
|
||||
<button type="button" disabled>↑</button>
|
||||
<button type="button" disabled>↓</button>
|
||||
<label><input id="playlist-enable-all" type="checkbox" checked disabled> 전체</label>
|
||||
<label><input id="moving-average-5" type="checkbox" checked> 5일선</label>
|
||||
<label><input id="moving-average-20" type="checkbox" checked> 20일선</label>
|
||||
<button id="playlist-move-up" type="button" disabled aria-label="선택 행 위로 이동">↑</button>
|
||||
<button id="playlist-move-down" type="button" disabled aria-label="선택 행 아래로 이동">↓</button>
|
||||
<span class="toolbar-spacer"></span>
|
||||
<label><input type="checkbox" disabled> 배경없음(F3)</label>
|
||||
<button type="button" disabled>배경파일(F2)</button>
|
||||
<input class="background-name" value="기본.vrv" readonly>
|
||||
<button type="button" disabled>DB 저장</button>
|
||||
<button type="button" disabled>DB 불러오기</button>
|
||||
<button type="button" disabled>선택삭제</button>
|
||||
<button type="button" disabled>전체삭제</button>
|
||||
<label><input id="playout-background-none" type="checkbox" disabled> 배경없음(F3)</label>
|
||||
<button id="playout-background-file" type="button" disabled>배경파일(F2)</button>
|
||||
<input id="playout-background-name" class="background-name" value="배경없음" readonly>
|
||||
<label class="fade-control" for="playout-fade-duration" hidden>효과</label>
|
||||
<select id="playout-fade-duration" disabled aria-label="장면 효과 시간" hidden>
|
||||
<option value="0">1</option><option value="1">2</option>
|
||||
<option value="2">3</option><option value="3">4</option>
|
||||
<option value="4">5</option><option value="5">6</option>
|
||||
<option value="6">7</option><option value="7">8</option>
|
||||
<option value="8">9</option><option value="9">10</option>
|
||||
<option value="10">11</option><option value="11">12</option>
|
||||
<option value="12">13</option><option value="13">14</option>
|
||||
<option value="14">15</option><option value="15">16</option>
|
||||
<option value="16">17</option><option value="17">18</option>
|
||||
<option value="18">19</option><option value="19">20</option>
|
||||
</select>
|
||||
<button id="db-save-button" type="button" disabled>DB 저장</button>
|
||||
<button id="db-load-button" type="button" disabled>DB 불러오기</button>
|
||||
<button id="playlist-delete-selected" type="button" disabled>선택삭제(DEL)</button>
|
||||
<button id="playlist-delete-all" type="button" disabled>전체삭제</button>
|
||||
</div>
|
||||
|
||||
<div id="playlist-drop-zone" class="playlist-grid">
|
||||
<div class="playlist-header playlist-row">
|
||||
<div>송출</div><div>종류</div><div>종목</div><div>컷파일</div><div>세부사항</div><div>Page</div>
|
||||
</div>
|
||||
<div id="playlist-rows" class="playlist-rows"></div>
|
||||
<div id="playlist-rows" class="playlist-rows" role="listbox" aria-label="송출 목록" aria-multiselectable="true"></div>
|
||||
</div>
|
||||
|
||||
<div class="playout-actions">
|
||||
<button class="take-in" type="button" disabled>● TAKE IN [F8]</button>
|
||||
<button class="next" type="button" disabled>▶ NEXT</button>
|
||||
<button class="take-out" type="button" disabled>✖ TAKE OUT[Esc]</button>
|
||||
<button id="playout-prepare" class="prepare" type="button" disabled hidden
|
||||
aria-hidden="true">PREPARE</button>
|
||||
<button id="playout-take-in" class="take-in" type="button" disabled>● TAKE IN [F8]</button>
|
||||
<button id="playout-next" class="next" type="button" disabled>▶ NEXT</button>
|
||||
<button id="playout-take-out" class="take-out" type="button" disabled>✖ TAKE OUT[Esc]</button>
|
||||
</div>
|
||||
<div class="playout-status">원본 호환 UI 기준선 · 송출 연결 안 함</div>
|
||||
<div id="playout-status" class="playout-status" aria-live="polite">송출 상태를 확인하고 있습니다.</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<div id="named-playlist-modal" class="named-playlist-backdrop" hidden>
|
||||
<section class="named-playlist-dialog" role="dialog" aria-modal="true"
|
||||
aria-labelledby="named-playlist-title">
|
||||
<header>
|
||||
<h2 id="named-playlist-title">DB 재생목록</h2>
|
||||
<button id="named-playlist-close" type="button" aria-label="닫기">×</button>
|
||||
</header>
|
||||
<div id="named-playlist-status" class="named-playlist-status" aria-live="polite"></div>
|
||||
<div class="named-playlist-body">
|
||||
<div id="named-playlist-definitions" class="named-playlist-definitions"
|
||||
role="listbox" aria-label="저장된 DB 재생목록"></div>
|
||||
<section class="named-playlist-create" aria-labelledby="named-playlist-create-title">
|
||||
<h3 id="named-playlist-create-title">새 재생목록</h3>
|
||||
<label for="named-playlist-new-title">이름</label>
|
||||
<input id="named-playlist-new-title" maxlength="128" autocomplete="off"
|
||||
spellcheck="false">
|
||||
<button id="named-playlist-create-button" type="button" disabled>새로 만들기</button>
|
||||
<p>DB 쓰기는 이 버튼 또는 저장·삭제 버튼을 누른 경우에만 한 번 실행됩니다.</p>
|
||||
</section>
|
||||
</div>
|
||||
<footer>
|
||||
<button id="named-playlist-delete-button" type="button" disabled>선택 삭제</button>
|
||||
<span class="named-playlist-footer-spacer"></span>
|
||||
<button id="named-playlist-cancel-button" type="button">취소</button>
|
||||
<button id="named-playlist-confirm-button" type="button" disabled>확인</button>
|
||||
</footer>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="manual-financial-modal" class="manual-financial-backdrop" hidden>
|
||||
<section class="manual-financial-dialog" role="dialog" aria-modal="true"
|
||||
aria-labelledby="manual-financial-title">
|
||||
<header>
|
||||
<h2 id="manual-financial-title">수동 재무 입력</h2>
|
||||
<button id="manual-financial-close" type="button" aria-label="닫기">×</button>
|
||||
</header>
|
||||
<div id="manual-financial-workspace" class="manual-financial-workspace"></div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="manual-list-modal" class="manual-list-backdrop" hidden>
|
||||
<section class="manual-list-dialog" role="dialog" aria-modal="true"
|
||||
aria-labelledby="manual-list-title">
|
||||
<header>
|
||||
<h2 id="manual-list-title">수동 송출 목록</h2>
|
||||
<button id="manual-list-close" type="button" aria-label="닫기">×</button>
|
||||
</header>
|
||||
<div id="manual-list-workspace" class="manual-list-workspace"></div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="operator-catalog-modal" class="operator-catalog-backdrop" hidden>
|
||||
<section class="operator-catalog-dialog" role="dialog" aria-modal="true"
|
||||
aria-labelledby="operator-catalog-title">
|
||||
<header>
|
||||
<h2 id="operator-catalog-title">ThemeA / EList 관리</h2>
|
||||
<button id="operator-catalog-close" type="button" aria-label="닫기">×</button>
|
||||
</header>
|
||||
<div id="operator-catalog-status" class="operator-catalog-status"
|
||||
aria-live="polite"></div>
|
||||
<div class="operator-catalog-toolbar">
|
||||
<button id="operator-catalog-theme-tab" type="button">ThemeA</button>
|
||||
<button id="operator-catalog-expert-tab" type="button">EList</button>
|
||||
<input id="operator-catalog-query" type="search" maxlength="64"
|
||||
autocomplete="off" placeholder="이름 검색">
|
||||
<select id="operator-catalog-session" aria-label="NXT 세션">
|
||||
<option value="preMarket">NXT 장전</option>
|
||||
<option value="afterMarket">NXT 시간외</option>
|
||||
</select>
|
||||
<button id="operator-catalog-search" type="button">검색</button>
|
||||
</div>
|
||||
<div class="operator-catalog-body">
|
||||
<section class="operator-catalog-list-panel" aria-labelledby="operator-catalog-list-title">
|
||||
<div class="operator-catalog-panel-header">
|
||||
<h3 id="operator-catalog-list-title">DB 목록</h3>
|
||||
<select id="operator-catalog-new-market" aria-label="새 ThemeA 시장">
|
||||
<option value="krx">KRX</option>
|
||||
<option value="nxt">NXT</option>
|
||||
</select>
|
||||
<button id="operator-catalog-new" type="button">새 항목</button>
|
||||
</div>
|
||||
<div id="operator-catalog-results" class="operator-catalog-results"
|
||||
role="listbox" aria-label="ThemeA EList 목록"></div>
|
||||
</section>
|
||||
<section id="operator-catalog-editor" class="operator-catalog-editor"
|
||||
aria-labelledby="operator-catalog-editor-title">
|
||||
<div class="operator-catalog-panel-header">
|
||||
<h3 id="operator-catalog-editor-title">추가·편집</h3>
|
||||
<span id="operator-catalog-code" class="operator-catalog-code"></span>
|
||||
</div>
|
||||
<label class="operator-catalog-name-field">
|
||||
<span id="operator-catalog-name-label">이름</span>
|
||||
<input id="operator-catalog-name" maxlength="128" autocomplete="off">
|
||||
</label>
|
||||
<div class="operator-catalog-stock-search">
|
||||
<input id="operator-catalog-stock-query" type="search" maxlength="64"
|
||||
autocomplete="off" placeholder="종목명 검색">
|
||||
<button id="operator-catalog-stock-search" type="button">종목 검색</button>
|
||||
</div>
|
||||
<div id="operator-catalog-stock-results" class="operator-catalog-stock-results"
|
||||
role="listbox" aria-label="stock master 검색 결과"></div>
|
||||
<div class="operator-catalog-add-line">
|
||||
<label id="operator-catalog-amount-label" for="operator-catalog-amount">매수가</label>
|
||||
<input id="operator-catalog-amount" type="number" min="1" step="1"
|
||||
inputmode="numeric">
|
||||
<button id="operator-catalog-add-stock" type="button">선택 종목 추가</button>
|
||||
</div>
|
||||
<div class="operator-catalog-draft-header">
|
||||
<strong>구성 종목</strong>
|
||||
<span>위·아래 버튼으로 송출 순서를 변경합니다.</span>
|
||||
</div>
|
||||
<div id="operator-catalog-draft-rows" class="operator-catalog-draft-rows"
|
||||
aria-label="ThemeA EList 구성 종목"></div>
|
||||
<footer class="operator-catalog-editor-actions">
|
||||
<button id="operator-catalog-delete" type="button">선택 삭제</button>
|
||||
<span></span>
|
||||
<button id="operator-catalog-cancel" type="button">편집 취소</button>
|
||||
<button id="operator-catalog-save" type="button">저장</button>
|
||||
</footer>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="legacy-dialog" class="dialog-backdrop" hidden>
|
||||
<div class="legacy-dialog" role="alertdialog" aria-modal="true" aria-labelledby="legacy-dialog-message">
|
||||
<div id="legacy-dialog-message"></div>
|
||||
@@ -110,5 +238,6 @@
|
||||
</div>
|
||||
|
||||
<script src="app.js"></script>
|
||||
<script src="playout-ui.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
172
src/MBN_STOCK_WEBVIEW.LegacyParityApp/Web/playout-ui.js
Normal file
172
src/MBN_STOCK_WEBVIEW.LegacyParityApp/Web/playout-ui.js
Normal file
@@ -0,0 +1,172 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
const webview = window.chrome && window.chrome.webview;
|
||||
const connection = document.getElementById("playout-connection-state");
|
||||
const prepare = document.getElementById("playout-prepare");
|
||||
const takeIn = document.getElementById("playout-take-in");
|
||||
const next = document.getElementById("playout-next");
|
||||
const takeOut = document.getElementById("playout-take-out");
|
||||
const backgroundNone = document.getElementById("playout-background-none");
|
||||
const backgroundFile = document.getElementById("playout-background-file");
|
||||
const backgroundName = document.getElementById("playout-background-name");
|
||||
const fadeDuration = document.getElementById("playout-fade-duration");
|
||||
const status = document.getElementById("playout-status");
|
||||
const controls = [prepare, takeIn, next, takeOut, backgroundNone,
|
||||
backgroundFile, fadeDuration];
|
||||
let currentState = null;
|
||||
let localBusy = false;
|
||||
|
||||
function hasOpenDialog() {
|
||||
return Array.from(document.querySelectorAll("[role='dialog'], [role='alertdialog']"))
|
||||
.some(function (dialog) {
|
||||
const container = dialog.closest("[hidden]");
|
||||
return !container && !dialog.hidden;
|
||||
});
|
||||
}
|
||||
|
||||
function post(type, payload) {
|
||||
if (!webview || localBusy || hasOpenDialog()) return;
|
||||
localBusy = true;
|
||||
render(currentState);
|
||||
webview.postMessage({ type: type, payload: payload || {} });
|
||||
}
|
||||
|
||||
function setAllDisabled(disabled) {
|
||||
controls.forEach(function (control) {
|
||||
if (control) control.disabled = disabled;
|
||||
});
|
||||
}
|
||||
|
||||
function phaseLabel(phase) {
|
||||
if (phase === "prepared") return "PREPARED";
|
||||
if (phase === "program") return "PROGRAM";
|
||||
return "IDLE";
|
||||
}
|
||||
|
||||
function connectionLabel(playout) {
|
||||
if (!playout) return "미연결";
|
||||
if (playout.outcomeUnknown) return "결과 불명확";
|
||||
if (playout.mode === "disabled") return "송출 비활성";
|
||||
if (playout.mode === "dryRun") return "DRY RUN";
|
||||
if (playout.isConnected) return "Tornado2 연결됨";
|
||||
if (playout.isProcessRunning) return "Tornado2 감지됨";
|
||||
return "미연결";
|
||||
}
|
||||
|
||||
function pageLabel(playout) {
|
||||
if (!playout || playout.pageCount <= 0) return "";
|
||||
return " · Page " + String(playout.pageIndexZeroBased + 1) +
|
||||
"/" + String(playout.pageCount);
|
||||
}
|
||||
|
||||
function nextLabel(playout) {
|
||||
if (!playout || playout.nextKind === "none") return "";
|
||||
return playout.nextKind === "pageNext" ? " · 다음 페이지" : " · 다음 항목";
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
currentState = state || currentState;
|
||||
const playout = currentState && currentState.playout;
|
||||
const nativeBusy = !!(currentState && currentState.isBusy) ||
|
||||
!!(playout && playout.isBusy);
|
||||
const busy = localBusy || nativeBusy;
|
||||
if (!playout) {
|
||||
connection.textContent = "미연결";
|
||||
status.textContent = "송출 엔진 상태를 사용할 수 없습니다.";
|
||||
setAllDisabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const commandAvailable = playout.isCommandAvailable === true &&
|
||||
playout.outcomeUnknown !== true;
|
||||
const hasPlaylist = Array.isArray(currentState.playlist) &&
|
||||
currentState.playlist.some(function (row) { return row.isEnabled === true; });
|
||||
const liveTakeInAllowed = playout.mode !== "live" ||
|
||||
playout.liveTakeInAllowed === true;
|
||||
const canPrepareToggle = playout.phase === "idle" ? hasPlaylist :
|
||||
playout.phase === "prepared" || playout.phase === "program";
|
||||
|
||||
connection.textContent = connectionLabel(playout);
|
||||
connection.classList.toggle("connected", playout.isConnected === true);
|
||||
connection.classList.toggle("outcome-unknown", playout.outcomeUnknown === true);
|
||||
prepare.classList.toggle("active", playout.phase !== "idle");
|
||||
prepare.disabled = busy || !commandAvailable || !canPrepareToggle ||
|
||||
playout.isPlayCompletionPending === true;
|
||||
const canTakeIn = playout.phase === "prepared" ||
|
||||
(playout.phase === "idle" && hasPlaylist);
|
||||
takeIn.disabled = busy || !commandAvailable || !liveTakeInAllowed ||
|
||||
!canTakeIn || playout.isPlayCompletionPending === true;
|
||||
next.disabled = busy || !commandAvailable ||
|
||||
playout.phase !== "program" || playout.nextKind === "none" ||
|
||||
playout.isPlayCompletionPending === true;
|
||||
takeOut.disabled = busy || !commandAvailable ||
|
||||
(playout.phase !== "prepared" && playout.phase !== "program");
|
||||
backgroundNone.disabled = busy || playout.canChangeBackground !== true;
|
||||
backgroundFile.disabled = busy || playout.canChangeBackground !== true;
|
||||
fadeDuration.disabled = busy || playout.canChangeBackground !== true;
|
||||
backgroundNone.checked = playout.backgroundEnabled !== true;
|
||||
backgroundName.value = playout.backgroundEnabled === true
|
||||
? (playout.backgroundFileName || "선택한 배경") : "배경없음";
|
||||
fadeDuration.value = String(playout.fadeDuration);
|
||||
|
||||
const scene = playout.onAirCode || playout.preparedCode;
|
||||
const sceneLabel = scene ? " · " + scene : "";
|
||||
const refresh = playout.refreshActive
|
||||
? " · 자동 갱신 " + String(playout.refreshCompletedCount) + "회" : "";
|
||||
status.textContent = phaseLabel(playout.phase) + sceneLabel +
|
||||
pageLabel(playout) + nextLabel(playout) + refresh +
|
||||
(playout.message ? " · " + playout.message : "");
|
||||
}
|
||||
|
||||
prepare.addEventListener("click", function () {
|
||||
post("prepare-playout", {});
|
||||
});
|
||||
takeIn.addEventListener("click", function () {
|
||||
post("take-in", {});
|
||||
});
|
||||
next.addEventListener("click", function () {
|
||||
post("next-playout", {});
|
||||
});
|
||||
takeOut.addEventListener("click", function () {
|
||||
post("take-out", {});
|
||||
});
|
||||
backgroundFile.addEventListener("click", function () {
|
||||
post("choose-background", {});
|
||||
});
|
||||
backgroundNone.addEventListener("change", function () {
|
||||
post("toggle-background", {});
|
||||
});
|
||||
fadeDuration.addEventListener("change", function () {
|
||||
post("set-fade-duration", { duration: Number(fadeDuration.value) });
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", function (event) {
|
||||
if (event.repeat || hasOpenDialog()) return;
|
||||
if (event.key === "F2") {
|
||||
event.preventDefault();
|
||||
if (!backgroundFile.disabled) backgroundFile.click();
|
||||
} else if (event.key === "F3") {
|
||||
event.preventDefault();
|
||||
if (!backgroundNone.disabled) backgroundNone.click();
|
||||
} else if (event.key === "F8") {
|
||||
event.preventDefault();
|
||||
if (!takeIn.disabled) takeIn.click();
|
||||
} else if (event.key === "Escape") {
|
||||
event.preventDefault();
|
||||
if (!takeOut.disabled) takeOut.click();
|
||||
}
|
||||
});
|
||||
|
||||
if (webview) {
|
||||
webview.addEventListener("message", function (event) {
|
||||
if (event.data && event.data.type === "state" && event.data.payload) {
|
||||
localBusy = false;
|
||||
render(event.data.payload);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
setAllDisabled(true);
|
||||
status.textContent = "WebView2 송출 브리지를 사용할 수 없습니다.";
|
||||
}
|
||||
}());
|
||||
@@ -7,6 +7,7 @@
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
*[hidden] { display: none !important; }
|
||||
html, body { width: 100%; height: 100%; margin: 0; overflow: hidden; }
|
||||
body.busy { cursor: wait; }
|
||||
body.busy .operator-shell { pointer-events: none; }
|
||||
@@ -32,6 +33,8 @@ button:disabled { color: #555; opacity: 1; }
|
||||
.brand span { color: #ed671f; font-size: 28px; font-weight: 800; letter-spacing: -2px; }
|
||||
.brand strong { font: italic 900 38px Arial, sans-serif; letter-spacing: -5px; }
|
||||
.connection-state { padding: 10px 12px; background: #c40000; color: white; font: 700 18px Consolas, monospace; }
|
||||
.connection-state.connected { background: #176c32; }
|
||||
.connection-state.outcome-unknown { background: #8a4d00; }
|
||||
|
||||
.search-line { display: grid; grid-template-columns: 40px 162px 1fr 117px; align-items: center; gap: 3px; height: 38px; }
|
||||
.search-line label { font-weight: 700; }
|
||||
@@ -45,6 +48,85 @@ button:disabled { color: #555; opacity: 1; }
|
||||
|
||||
.manual-actions { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin: 9px 0; }
|
||||
.manual-actions button { height: 34px; font-size: 12px; font-weight: 700; }
|
||||
.manual-list-actions { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin: 0 0 9px; }
|
||||
.manual-list-actions button { height: 31px; padding: 2px 3px; font-size: 11px; font-weight: 700; }
|
||||
|
||||
.named-playlist-backdrop { position: fixed; inset: 0; z-index: 19; background: rgba(0, 0, 0, .3); }
|
||||
.named-playlist-backdrop[hidden] { display: none; }
|
||||
.named-playlist-dialog { position: absolute; left: 50%; top: 50%; width: 650px; height: 500px; transform: translate(-50%, -50%); display: grid; grid-template-rows: 45px auto minmax(0, 1fr) 52px; border: 1px solid #666; background: #f2f2f2; box-shadow: 0 10px 36px rgba(0, 0, 0, .4); }
|
||||
.named-playlist-dialog > header { display: flex; align-items: center; justify-content: space-between; padding: 0 12px; border-bottom: 1px solid #999; background: #ececec; }
|
||||
.named-playlist-dialog h2 { margin: 0; font-size: 18px; }
|
||||
.named-playlist-dialog > header button { width: 34px; height: 29px; font-size: 20px; }
|
||||
.named-playlist-status { min-height: 38px; padding: 8px 12px; border-bottom: 1px solid #bbb; color: #444; }
|
||||
.named-playlist-status.error { background: #fff1f3; color: #9b001b; font-weight: 700; }
|
||||
.named-playlist-body { min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) 230px; gap: 9px; padding: 10px; }
|
||||
.named-playlist-definitions { min-height: 0; overflow: auto; border: 1px solid #888; background: #fff; }
|
||||
.named-playlist-definitions button { display: block; width: 100%; min-height: 28px; padding: 4px 8px; border: 0; border-bottom: 1px solid #ddd; background: #fff; text-align: left; }
|
||||
.named-playlist-definitions button.selected { background: #d9e8f9; font-weight: 700; }
|
||||
.named-playlist-create { align-self: start; display: grid; grid-template-columns: 1fr; gap: 7px; padding: 10px; border: 1px solid #aaa; background: #fff; }
|
||||
.named-playlist-create h3 { margin: 0 0 5px; font-size: 15px; }
|
||||
.named-playlist-create input, .named-playlist-create button { min-width: 0; height: 30px; }
|
||||
.named-playlist-create p { margin: 5px 0 0; color: #555; font-size: 11px; line-height: 1.45; }
|
||||
.named-playlist-dialog > footer { display: flex; align-items: center; gap: 8px; padding: 9px 11px; border-top: 1px solid #aaa; }
|
||||
.named-playlist-dialog > footer button { min-width: 96px; height: 32px; }
|
||||
.named-playlist-footer-spacer { flex: 1; }
|
||||
.named-playlist-dialog > footer #named-playlist-confirm-button { border-color: #4774a8; background: linear-gradient(#f8fbff, #d9e8f9); font-weight: 700; }
|
||||
|
||||
.manual-financial-backdrop { position: fixed; inset: 0; z-index: 18; background: rgba(0, 0, 0, .3); }
|
||||
.manual-financial-backdrop[hidden] { display: none; }
|
||||
.manual-financial-dialog { position: absolute; left: 50%; top: 50%; width: min(1120px, 92vw); height: min(800px, 90vh); transform: translate(-50%, -50%); display: grid; grid-template-rows: 46px minmax(0, 1fr); border: 1px solid #666; background: #f3f3f3; box-shadow: 0 10px 36px rgba(0, 0, 0, .4); }
|
||||
.manual-financial-dialog > header { display: flex; align-items: center; justify-content: space-between; padding: 0 12px; border-bottom: 1px solid #999; background: #ececec; }
|
||||
.manual-financial-dialog h2 { margin: 0; font-size: 18px; }
|
||||
.manual-financial-dialog > header button { width: 34px; height: 29px; font-size: 20px; }
|
||||
.manual-financial-workspace { min-height: 0; display: grid; grid-template-rows: 38px minmax(0, 1fr); gap: 7px; padding: 8px; }
|
||||
.manual-financial-toolbar { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 5px; }
|
||||
.manual-financial-toolbar input, .manual-financial-toolbar button { min-width: 0; height: 30px; }
|
||||
.manual-financial-body { min-height: 0; display: grid; grid-template-columns: 270px minmax(0, 1fr); gap: 8px; }
|
||||
.manual-financial-list { min-height: 0; overflow: auto; border: 1px solid #999; background: #fff; }
|
||||
.manual-financial-list button { display: block; width: 100%; min-height: 25px; padding: 3px 7px; border: 0; border-bottom: 1px solid #ddd; background: #fff; text-align: left; }
|
||||
.manual-financial-list button.selected { background: #dcdcdc; }
|
||||
.manual-financial-list button.manual-financial-list-header { position: sticky; top: 0; z-index: 1; background: #ececec; border-bottom: 1px solid #888; font-weight: 700; }
|
||||
.manual-financial-editor { min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 7px; padding: 8px; border: 1px solid #999; background: #fff; }
|
||||
.manual-financial-stock-line { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 5px; }
|
||||
.manual-financial-stock-line input, .manual-financial-stock-line button { height: 30px; }
|
||||
.manual-financial-stock-results { display: flex; flex-wrap: wrap; gap: 4px; min-height: 28px; max-height: 84px; overflow: auto; padding: 3px; border: 1px solid #ccc; }
|
||||
.manual-financial-stock-results button { padding: 3px 7px; }
|
||||
.manual-financial-stock-results button.selected { border-color: #145ab4; background: #dceaff; }
|
||||
.manual-financial-verification { min-height: 22px; color: #145ab4; }
|
||||
.manual-financial-fields { display: grid; gap: 7px; }
|
||||
.manual-financial-field { display: grid; grid-template-columns: 100px minmax(0, 1fr); align-items: center; gap: 6px; }
|
||||
.manual-financial-field input { min-width: 0; height: 28px; }
|
||||
.manual-financial-grid { display: grid; gap: 4px; align-items: center; }
|
||||
.manual-financial-grid input { min-width: 0; height: 27px; }
|
||||
.manual-revenue-grid, .manual-quarter-grid { grid-template-columns: minmax(0, 1fr) minmax(120px, .45fr); }
|
||||
.manual-growth-grid { grid-template-columns: 130px repeat(4, minmax(90px, 1fr)); }
|
||||
.manual-financial-actions { margin-top: auto; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
|
||||
.manual-financial-actions button { min-height: 34px; }
|
||||
.manual-financial-actions .manual-primary { border-color: #4774a8; background: linear-gradient(#f8fbff, #d9e8f9); font-weight: 700; }
|
||||
.manual-financial-message { color: #444; }
|
||||
.manual-financial-warning { padding: 7px; border: 1px solid #b00020; background: #fff1f3; color: #9b001b; font-weight: 700; }
|
||||
.manual-list-backdrop { position: fixed; inset: 0; z-index: 19; background: rgba(0, 0, 0, .32); }
|
||||
.manual-list-backdrop[hidden] { display: none; }
|
||||
.manual-list-dialog { position: absolute; left: 50%; top: 50%; width: min(980px, 94vw); height: min(760px, 91vh); transform: translate(-50%, -50%); display: grid; grid-template-rows: 46px minmax(0, 1fr); border: 1px solid #666; background: #f3f3f3; box-shadow: 0 10px 36px rgba(0, 0, 0, .4); }
|
||||
.manual-list-dialog > header { display: flex; align-items: center; justify-content: space-between; padding: 0 12px; border-bottom: 1px solid #999; }
|
||||
.manual-list-dialog h2 { margin: 0; font-size: 18px; }
|
||||
.manual-list-dialog > header button { width: 34px; height: 29px; font-size: 20px; }
|
||||
.manual-list-workspace { min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 8px; padding: 10px; }
|
||||
.manual-list-tabs, .manual-list-actions-row, .manual-list-search { display: flex; gap: 6px; align-items: center; }
|
||||
.manual-list-tabs button.active { border-color: #145ab4; background: #dceaff; font-weight: 700; }
|
||||
.manual-list-table-wrap { min-height: 0; overflow: auto; border: 1px solid #999; background: #fff; }
|
||||
.manual-list-table { width: 100%; border-collapse: collapse; }
|
||||
.manual-list-table th, .manual-list-table td { padding: 4px; border-right: 1px solid #ddd; border-bottom: 1px solid #ddd; }
|
||||
.manual-list-table input { width: 100%; min-width: 0; height: 27px; }
|
||||
.manual-list-table .manual-list-row-actions { width: 170px; white-space: nowrap; }
|
||||
.manual-list-search input { flex: 1; min-width: 0; height: 30px; }
|
||||
.manual-list-search-results { display: flex; flex-wrap: wrap; gap: 4px; max-height: 110px; overflow: auto; padding: 5px; border: 1px solid #aaa; background: #fff; }
|
||||
.manual-list-search-results button.selected { background: #dcdcdc; font-weight: 600; }
|
||||
.manual-list-status { padding: 7px; border: 1px solid #bbb; background: #fff; }
|
||||
.manual-list-status.error { border-color: #b00020; background: #fff1f3; color: #9b001b; font-weight: 700; }
|
||||
.manual-list-actions-row { margin-top: auto; justify-content: flex-end; }
|
||||
.manual-list-actions-row button { min-width: 100px; height: 34px; }
|
||||
.manual-list-actions-row .primary { border-color: #4774a8; background: linear-gradient(#f8fbff, #d9e8f9); font-weight: 700; }
|
||||
|
||||
.cut-list { flex: 1; min-height: 0; border: 1px solid #999; background: #fff; overflow-y: auto; user-select: none; }
|
||||
.cut-row { display: grid; grid-template-columns: 62px 1fr; min-height: 23px; border-bottom: 1px solid #ddd; background: #fff; font-size: 15px; }
|
||||
@@ -63,13 +145,123 @@ button:disabled { color: #555; opacity: 1; }
|
||||
.category-tree { flex: 1; overflow: auto; padding: 7px 12px; background: #fff; border-left: 1px solid #aaa; border-right: 1px solid #aaa; }
|
||||
.tree-root { margin: 5px 0 2px; color: #168000; font-size: 16px; }
|
||||
.tree-root.second { margin-top: 15px; }
|
||||
.tree-item { padding: 3px 0 3px 29px; font-size: 15px; }
|
||||
.catalog-section > summary { margin: 5px 0 2px; color: #168000; font-size: 16px; cursor: default; user-select: none; }
|
||||
.catalog-actions { display: grid; }
|
||||
.tree-item { width: 100%; padding: 3px 0 3px 29px; border: 0; background: transparent; color: #111; font: inherit; font-size: 15px; text-align: left; cursor: default; }
|
||||
.tree-item:hover, .tree-item:focus-visible { background: #dcdcdc; outline: none; }
|
||||
.tree-item.unavailable { color: #777; }
|
||||
.industry-workspace { display: grid; grid-template-rows: minmax(170px, 42%) minmax(0, 1fr); height: 100%; gap: 7px; }
|
||||
.industry-selector { display: grid; grid-template-rows: auto minmax(0, 1fr); min-height: 0; }
|
||||
.industry-slots { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 4px; margin-bottom: 5px; }
|
||||
.industry-slots input { min-width: 0; }
|
||||
.industry-list { overflow: auto; border: 1px solid #aaa; background: #fff; }
|
||||
.industry-list button { display: block; width: 100%; padding: 2px 7px; border: 0; background: #fff; text-align: left; }
|
||||
.industry-list button.selected { background: #dcdcdc; }
|
||||
.industry-action-tree { min-height: 0; overflow: auto; border-top: 1px solid #aaa; padding-top: 4px; }
|
||||
.industry-action-tree summary { color: #168000; font-size: 15px; cursor: default; }
|
||||
.overseas-workspace { display: grid; grid-template-rows: minmax(92px, 20%) minmax(170px, 42%) minmax(0, 1fr); height: 100%; gap: 7px; }
|
||||
.overseas-panel { min-height: 0; }
|
||||
.overseas-panel h3 { margin: 0 0 4px; color: #168000; font-size: 14px; font-weight: 600; }
|
||||
.overseas-fixed-panel { display: grid; grid-template-rows: auto minmax(0, 1fr); }
|
||||
.overseas-fixed-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); overflow: auto; border: 1px solid #aaa; background: #fff; }
|
||||
.overseas-fixed-list button { min-width: 0; padding: 2px 5px; border-width: 0 1px 1px 0; background: #fff; text-align: left; }
|
||||
.overseas-fixed-list button.selected { background: #dcdcdc; font-weight: 600; }
|
||||
.overseas-searches { display: grid; grid-template-columns: 1fr 1fr; min-height: 0; gap: 7px; }
|
||||
.overseas-search-panel { display: grid; grid-template-rows: auto auto auto minmax(0, 1fr) auto; }
|
||||
.overseas-search-line { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px; }
|
||||
.overseas-search-line input { min-width: 0; }
|
||||
.overseas-selected, .overseas-note { min-height: 18px; padding: 2px 3px; color: #444; font-size: 11px; }
|
||||
.overseas-note.error { color: #a40000; }
|
||||
.overseas-results { min-height: 0; overflow: auto; border: 1px solid #aaa; background: #fff; }
|
||||
.overseas-results button { display: block; width: 100%; padding: 2px 5px; border: 0; background: #fff; text-align: left; }
|
||||
.overseas-results button.selected { background: #dcdcdc; }
|
||||
.overseas-action-panel { overflow: auto; border-top: 1px solid #aaa; padding-top: 4px; }
|
||||
.overseas-action-panel summary { color: #168000; font-size: 15px; cursor: default; }
|
||||
.comparison-workspace { display: grid; grid-template-rows: minmax(110px, 22%) minmax(70px, 16%) minmax(150px, 1fr) auto; height: 100%; gap: 6px; }
|
||||
.comparison-searches { display: grid; grid-template-columns: 1fr 1fr; min-height: 0; gap: 6px; }
|
||||
.comparison-search-panel { display: grid; grid-template-rows: auto minmax(0, 1fr); min-height: 0; }
|
||||
.comparison-search-line { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px; }
|
||||
.comparison-results, .comparison-saved { min-height: 0; overflow: auto; border: 1px solid #aaa; background: #fff; }
|
||||
.comparison-results button, .comparison-saved button { display: block; width: 100%; padding: 2px 5px; border: 0; background: #fff; text-align: left; }
|
||||
.comparison-results button:hover, .comparison-results button.selected, .comparison-saved button.selected { background: #dcdcdc; }
|
||||
.comparison-fixed { display: grid; grid-template-rows: auto minmax(0, 1fr); min-height: 0; }
|
||||
.comparison-fixed-list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); overflow: auto; border: 1px solid #aaa; }
|
||||
.comparison-fixed-list button { padding: 2px 4px; text-align: left; }
|
||||
.comparison-fixed-list button.selected { background: #dcdcdc; font-weight: 600; }
|
||||
.comparison-pair-panel { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; min-height: 0; gap: 4px; }
|
||||
.comparison-draft { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto auto; gap: 4px; }
|
||||
.comparison-draft input { min-width: 0; }
|
||||
.comparison-saved-tools { display: flex; gap: 4px; justify-content: flex-end; }
|
||||
.comparison-actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px; }
|
||||
.theme-workspace { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; height: 100%; gap: 7px; }
|
||||
.theme-search-line { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 5px; }
|
||||
.theme-search-line #theme-search { grid-column: span 2; min-width: 0; }
|
||||
.theme-search-line button[data-uc4-theme-catalog="create"] { grid-column: 2; }
|
||||
.theme-body { display: grid; grid-template-columns: minmax(150px, 42%) minmax(0, 1fr); min-height: 0; gap: 7px; }
|
||||
.theme-results, .theme-preview-panel { min-height: 0; overflow: auto; border: 1px solid #aaa; background: #fff; }
|
||||
.theme-results button { display: block; width: 100%; padding: 3px 6px; border: 0; background: #fff; text-align: left; }
|
||||
.theme-results button.selected { background: #dcdcdc; }
|
||||
.theme-preview-panel { display: grid; grid-template-rows: auto auto minmax(0, 1fr); gap: 4px; padding: 5px; }
|
||||
.theme-preview-list { overflow: auto; margin: 0; padding-left: 28px; }
|
||||
.theme-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px; }
|
||||
.expert-workspace, .halt-workspace { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; height: 100%; gap: 7px; }
|
||||
.expert-search-line { display: grid; grid-template-columns: minmax(0, 1fr) repeat(3, auto); gap: 5px; }
|
||||
.expert-body { display: grid; grid-template-columns: minmax(150px, 40%) minmax(0, 1fr); min-height: 0; gap: 7px; }
|
||||
.expert-results, .expert-preview, .halt-results { min-height: 0; overflow: auto; border: 1px solid #aaa; background: #fff; }
|
||||
.expert-results button, .halt-results button { display: block; width: 100%; padding: 3px 6px; border: 0; background: #fff; text-align: left; }
|
||||
.expert-results button.selected, .halt-results button.selected { background: #dcdcdc; }
|
||||
.expert-preview { padding: 6px; }
|
||||
.expert-preview ol { margin: 5px 0 0; padding-left: 28px; }
|
||||
.expert-actions, .halt-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px; }
|
||||
.halt-search-line { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 5px; }
|
||||
|
||||
.operator-catalog-backdrop { position: fixed; inset: 0; z-index: 24; display: grid; place-items: center; background: rgba(0, 0, 0, .36); }
|
||||
.operator-catalog-backdrop[hidden] { display: none; }
|
||||
.operator-catalog-dialog { display: grid; grid-template-rows: auto auto auto minmax(0, 1fr); width: min(1160px, calc(100vw - 70px)); height: min(820px, calc(100vh - 60px)); overflow: hidden; border: 1px solid #555; background: #efefef; box-shadow: 0 12px 42px rgba(0, 0, 0, .38); }
|
||||
.operator-catalog-dialog > header { display: flex; align-items: center; min-height: 48px; padding: 7px 12px; border-bottom: 1px solid #888; background: #fff; }
|
||||
.operator-catalog-dialog > header h2 { flex: 1; margin: 0; font-size: 20px; }
|
||||
.operator-catalog-dialog > header button { width: 38px; height: 32px; font-size: 22px; }
|
||||
.operator-catalog-status { min-height: 34px; padding: 8px 12px; border-bottom: 1px solid #bbb; color: #333; background: #f8f8f8; }
|
||||
.operator-catalog-status.error { color: #a40000; background: #fff0f0; font-weight: 600; }
|
||||
.operator-catalog-toolbar { display: grid; grid-template-columns: 94px 94px minmax(240px, 1fr) 120px 80px; gap: 6px; padding: 8px 12px; border-bottom: 1px solid #aaa; }
|
||||
.operator-catalog-toolbar button.selected { color: #fff; background: #176b2d; font-weight: 700; }
|
||||
.operator-catalog-body { display: grid; grid-template-columns: minmax(280px, 34%) minmax(0, 1fr); min-height: 0; gap: 10px; padding: 10px 12px 12px; }
|
||||
.operator-catalog-list-panel, .operator-catalog-editor { display: grid; min-height: 0; border: 1px solid #999; background: #fff; }
|
||||
.operator-catalog-list-panel { grid-template-rows: auto minmax(0, 1fr); }
|
||||
.operator-catalog-panel-header { display: flex; align-items: center; min-height: 40px; gap: 6px; padding: 6px 8px; border-bottom: 1px solid #bbb; background: #f3f3f3; }
|
||||
.operator-catalog-panel-header h3 { flex: 1; margin: 0; font-size: 15px; }
|
||||
.operator-catalog-code { color: #555; font-family: Consolas, monospace; }
|
||||
.operator-catalog-results, .operator-catalog-stock-results, .operator-catalog-draft-rows { min-height: 0; overflow: auto; }
|
||||
.operator-catalog-results button { display: grid; grid-template-columns: 84px minmax(0, 1fr); width: 100%; gap: 2px 8px; padding: 6px 8px; border: 0; border-bottom: 1px solid #ddd; background: #fff; text-align: left; }
|
||||
.operator-catalog-results button small { grid-column: 2; color: #666; }
|
||||
.operator-catalog-results button.selected { background: #dcebdc; }
|
||||
.operator-catalog-editor { grid-template-rows: auto auto auto minmax(92px, 20%) auto auto minmax(120px, 1fr) auto; gap: 7px; padding-bottom: 8px; }
|
||||
.operator-catalog-editor[hidden] { display: none; }
|
||||
.operator-catalog-name-field { display: grid; grid-template-columns: 76px minmax(0, 1fr); align-items: center; gap: 6px; padding: 0 9px; }
|
||||
.operator-catalog-stock-search { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px; padding: 0 9px; }
|
||||
.operator-catalog-stock-results { margin: 0 9px; border: 1px solid #aaa; }
|
||||
.operator-catalog-stock-results button { display: grid; grid-template-columns: minmax(0, 1fr) auto; width: 100%; padding: 4px 7px; border: 0; border-bottom: 1px solid #ddd; background: #fff; text-align: left; }
|
||||
.operator-catalog-stock-results button.selected { background: #dcebdc; }
|
||||
.operator-catalog-stock-results button:disabled { color: #999; }
|
||||
.operator-catalog-add-line { display: grid; grid-template-columns: auto 150px minmax(130px, auto); justify-content: end; align-items: center; gap: 6px; padding: 0 9px; }
|
||||
.operator-catalog-add-line [hidden] { display: none; }
|
||||
.operator-catalog-draft-header { display: flex; justify-content: space-between; gap: 8px; padding: 2px 9px; color: #555; }
|
||||
.operator-catalog-draft-header span { font-size: 11px; }
|
||||
.operator-catalog-draft-rows { margin: 0 9px; border: 1px solid #aaa; }
|
||||
.operator-catalog-draft-row { display: grid; grid-template-columns: 34px minmax(140px, 1fr) minmax(110px, auto) 36px 36px 58px; align-items: center; gap: 4px; min-height: 34px; padding: 3px 5px; border-bottom: 1px solid #ddd; }
|
||||
.operator-catalog-draft-row > span { text-align: center; }
|
||||
.operator-catalog-draft-row > small { color: #555; text-align: right; }
|
||||
.operator-catalog-draft-row > input { min-width: 90px; width: 100%; height: 27px; text-align: right; }
|
||||
.operator-catalog-editor-actions { display: grid; grid-template-columns: auto 1fr auto auto; gap: 7px; padding: 2px 9px 0; }
|
||||
.operator-catalog-editor-actions button:last-child { min-width: 92px; color: #fff; background: #176b2d; font-weight: 700; }
|
||||
|
||||
.playlist-panel { display: grid; grid-template-rows: 58px minmax(0, 1fr) 76px 42px; padding: 0 8px; background: #efefef; }
|
||||
.playlist-toolbar { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
|
||||
.playlist-toolbar button { height: 25px; padding: 2px 9px; }
|
||||
.playlist-toolbar { display: flex; align-items: center; gap: 5px; white-space: nowrap; }
|
||||
.playlist-toolbar button { height: 25px; padding: 2px 7px; }
|
||||
.playlist-toolbar .toolbar-spacer { flex: 1; }
|
||||
.background-name { width: 95px; height: 25px; border: 1px solid #888; background: #fff; }
|
||||
.background-name { width: 82px; height: 25px; border: 1px solid #888; background: #fff; }
|
||||
.fade-control { margin-left: 2px; }
|
||||
#playout-fade-duration { width: 48px; height: 25px; }
|
||||
|
||||
.playlist-grid { min-height: 0; border: 1px solid #888; background: #d5d5d5; overflow: auto; }
|
||||
.playlist-row { display: grid; grid-template-columns: 40px 100px 260px 200px minmax(255px, 1fr) 52px; min-width: 907px; }
|
||||
@@ -78,12 +270,14 @@ button:disabled { color: #555; opacity: 1; }
|
||||
.playlist-data-row { min-height: 25px; background: #fff; border-bottom: 1px solid #ddd; }
|
||||
.playlist-data-row > div { padding: 3px 6px; border-right: 1px solid #ddd; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.playlist-data-row .enabled-cell { text-align: center; }
|
||||
.playlist-data-row.selected { background: #dcdcdc; }
|
||||
.playlist-data-row:focus { outline: 1px dotted #333; outline-offset: -2px; }
|
||||
|
||||
.playout-actions { display: flex; align-items: center; justify-content: space-between; gap: 18px; }
|
||||
.playout-actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: center; gap: 12px; }
|
||||
.playout-actions button { height: 51px; background: #fff; font-size: 25px; font-weight: 700; }
|
||||
.take-in { width: 215px; }
|
||||
.next { width: 180px; }
|
||||
.take-out { width: 212px; }
|
||||
.playout-actions button:disabled { color: #888; background: #f7f7f7; }
|
||||
.playout-actions .prepare { font-size: 21px; }
|
||||
.playout-actions .prepare.active { color: #fff; background: #1a7700; }
|
||||
.playout-status { border-top: 1px solid #bbb; display: flex; align-items: center; justify-content: center; color: #666; }
|
||||
|
||||
.dialog-backdrop { position: fixed; inset: 0; z-index: 20; background: rgba(0, 0, 0, .25); }
|
||||
|
||||
Reference in New Issue
Block a user