Initial commit
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
// File Explorer JavaScript functions
|
||||
|
||||
let escapeKeyHandler = null;
|
||||
|
||||
export function registerEscapeKeyHandler(dotNetHelper) {
|
||||
// Remove existing handler if any
|
||||
if (escapeKeyHandler) {
|
||||
document.removeEventListener('keydown', escapeKeyHandler);
|
||||
}
|
||||
|
||||
// Create new handler
|
||||
escapeKeyHandler = (e) => {
|
||||
if (e.key === 'Escape' || e.key === 'Esc') {
|
||||
dotNetHelper.invokeMethodAsync('HandleEscapeKey');
|
||||
}
|
||||
};
|
||||
|
||||
// Register handler
|
||||
document.addEventListener('keydown', escapeKeyHandler);
|
||||
}
|
||||
|
||||
export function unregisterEscapeKeyHandler() {
|
||||
if (escapeKeyHandler) {
|
||||
document.removeEventListener('keydown', escapeKeyHandler);
|
||||
escapeKeyHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
export function init(treeContainerRef) {
|
||||
// Initialize file explorer if needed
|
||||
}
|
||||
|
||||
export function updateFolderBadges(folderPath, hasWarnings, hasErrors, isModified, warningCount, errorCount, folderName) {
|
||||
// Update folder badges via DOM manipulation
|
||||
const folderElement = document.querySelector(`[data-folder-path="${folderPath}"]`);
|
||||
if (folderElement) {
|
||||
const warningBadge = folderElement.querySelector('[data-badge="warning"]');
|
||||
const errorBadge = folderElement.querySelector('[data-badge="error"]');
|
||||
const modifiedBadge = folderElement.querySelector('[data-badge="modified"]');
|
||||
|
||||
if (warningBadge) {
|
||||
warningBadge.style.display = hasWarnings ? 'inline' : 'none';
|
||||
warningBadge.textContent = warningCount;
|
||||
warningBadge.setAttribute('data-count', warningCount);
|
||||
}
|
||||
|
||||
if (errorBadge) {
|
||||
errorBadge.style.display = hasErrors ? 'inline' : 'none';
|
||||
errorBadge.textContent = errorCount;
|
||||
errorBadge.setAttribute('data-count', errorCount);
|
||||
}
|
||||
|
||||
if (modifiedBadge) {
|
||||
modifiedBadge.style.display = isModified ? 'inline' : 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function updateFileBadges(filePath, hasWarnings, hasErrors, isModified, warningCount, errorCount, fileName) {
|
||||
// Update file badges via DOM manipulation
|
||||
const fileElement = document.querySelector(`[data-file-path="${filePath}"]`);
|
||||
if (fileElement) {
|
||||
const warningBadge = fileElement.querySelector('[data-badge="warning"]');
|
||||
const errorBadge = fileElement.querySelector('[data-badge="error"]');
|
||||
const modifiedBadge = fileElement.querySelector('[data-badge="modified"]');
|
||||
|
||||
if (warningBadge) {
|
||||
warningBadge.style.display = hasWarnings ? 'inline' : 'none';
|
||||
warningBadge.textContent = warningCount;
|
||||
warningBadge.setAttribute('data-count', warningCount);
|
||||
}
|
||||
|
||||
if (errorBadge) {
|
||||
errorBadge.style.display = hasErrors ? 'inline' : 'none';
|
||||
errorBadge.textContent = errorCount;
|
||||
errorBadge.setAttribute('data-count', errorCount);
|
||||
}
|
||||
|
||||
if (modifiedBadge) {
|
||||
modifiedBadge.style.display = isModified ? 'inline' : 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function UncheckRadioByName(radioName) {
|
||||
const radios = document.querySelectorAll(`input[type="radio"][name="${radioName}"]`);
|
||||
radios.forEach(radio => {
|
||||
radio.checked = false;
|
||||
});
|
||||
}
|
||||
|
||||
export function CheckRadioById(itemId) {
|
||||
const radio = document.getElementById(itemId);
|
||||
if (radio) {
|
||||
radio.checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
export function setElementPosition(elementId, x, y) {
|
||||
const element = document.getElementById(elementId);
|
||||
if (element) {
|
||||
element.style.position = 'fixed';
|
||||
element.style.left = x + 'px';
|
||||
element.style.top = y + 'px';
|
||||
element.style.width = '1px';
|
||||
element.style.height = '1px';
|
||||
element.style.pointerEvents = 'none';
|
||||
element.style.zIndex = '-1';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
// Layout handlers cho ScriptEditor - xử lý tất cả logic layout bằng JavaScript
|
||||
|
||||
let sidebarResizer = null;
|
||||
let consoleResizer = null;
|
||||
let isResizingSidebar = false;
|
||||
let isResizingConsole = false;
|
||||
let accordionHeaders = [];
|
||||
let activeTab = null;
|
||||
|
||||
export function initializeLayout() {
|
||||
initializeResizeHandlers();
|
||||
initializeAccordion();
|
||||
}
|
||||
|
||||
function initializeAccordion() {
|
||||
// Reset state
|
||||
activeTab = null;
|
||||
|
||||
// Tìm tất cả accordion headers
|
||||
accordionHeaders = document.querySelectorAll('.sidebar-accordion-header');
|
||||
|
||||
accordionHeaders.forEach(header => {
|
||||
header.addEventListener('click', handleAccordionClick);
|
||||
});
|
||||
|
||||
// Mở tab đầu tiên mặc định (workspace)
|
||||
const firstTab = document.querySelector('[data-tab="workspace"]');
|
||||
if (firstTab) {
|
||||
toggleAccordionTab(firstTab, true);
|
||||
activeTab = 'workspace'; // Quan trọng: set activeTab để đồng bộ với UI
|
||||
}
|
||||
}
|
||||
|
||||
function handleAccordionClick(e) {
|
||||
const header = e.currentTarget;
|
||||
const accordionItem = header.closest('.sidebar-accordion-item');
|
||||
|
||||
if (!accordionItem) return;
|
||||
|
||||
// Kiểm tra nếu click vào accordion-header-actions hoặc các phần tử con của nó thì không toggle
|
||||
const actionsContainer = header.querySelector('.accordion-header-actions');
|
||||
if (actionsContainer && (actionsContainer.contains(e.target) || actionsContainer === e.target)) {
|
||||
return; // Không xử lý toggle nếu click vào actions container
|
||||
}
|
||||
|
||||
const tabName = accordionItem.getAttribute('data-tab');
|
||||
const isCurrentlyActive = activeTab === tabName;
|
||||
|
||||
// Nếu click vào tab đang active thì đóng nó, ngược lại mở tab mới
|
||||
if (isCurrentlyActive) {
|
||||
toggleAccordionTab(accordionItem, false);
|
||||
activeTab = null;
|
||||
} else {
|
||||
// Đóng tab cũ nếu có
|
||||
if (activeTab) {
|
||||
const oldTab = document.querySelector(`[data-tab="${activeTab}"]`);
|
||||
if (oldTab) {
|
||||
toggleAccordionTab(oldTab, false);
|
||||
}
|
||||
}
|
||||
// Mở tab mới
|
||||
toggleAccordionTab(accordionItem, true);
|
||||
activeTab = tabName;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleAccordionTab(accordionItem, expand) {
|
||||
const header = accordionItem.querySelector('.sidebar-accordion-header');
|
||||
const content = accordionItem.querySelector('.sidebar-accordion-content');
|
||||
const arrow = accordionItem.querySelector('.accordion-arrow');
|
||||
|
||||
if (!header || !content || !arrow) return;
|
||||
|
||||
if (expand) {
|
||||
header.classList.add('active');
|
||||
content.classList.remove('collapsed');
|
||||
content.classList.add('expanded');
|
||||
arrow.textContent = '▼';
|
||||
} else {
|
||||
header.classList.remove('active');
|
||||
content.classList.remove('expanded');
|
||||
content.classList.add('collapsed');
|
||||
arrow.textContent = '▶';
|
||||
}
|
||||
}
|
||||
|
||||
function initializeResizeHandlers() {
|
||||
sidebarResizer = document.querySelector('.sidebar-resizer');
|
||||
consoleResizer = document.querySelector('.vertical-resizer');
|
||||
|
||||
// Khởi tạo chiều cao mặc định cho editor và console
|
||||
const container = document.querySelector('.editor-console-container');
|
||||
const editorArea = document.querySelector('#editor-area');
|
||||
const consolePanel = document.querySelector('#console-panel');
|
||||
|
||||
if (container && editorArea && consolePanel) {
|
||||
const containerHeight = container.clientHeight;
|
||||
const consoleHeight = 200; // Chiều cao khởi tạo ban đầu cho console
|
||||
const editorHeight = containerHeight - consoleHeight - 4; // 4px cho resizer
|
||||
|
||||
editorArea.style.height = editorHeight + 'px';
|
||||
consolePanel.style.height = consoleHeight + 'px';
|
||||
}
|
||||
|
||||
if (sidebarResizer) {
|
||||
sidebarResizer.addEventListener('mousedown', (e) => {
|
||||
isResizingSidebar = true;
|
||||
document.addEventListener('mousemove', handleSidebarResize);
|
||||
document.addEventListener('mouseup', stopSidebarResize);
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
if (consoleResizer) {
|
||||
consoleResizer.addEventListener('mousedown', (e) => {
|
||||
isResizingConsole = true;
|
||||
// Thêm class resizing ngay khi bắt đầu để disable transition
|
||||
const consolePanel = document.querySelector('#console-panel');
|
||||
const editorArea = document.querySelector('#editor-area');
|
||||
if (consolePanel) consolePanel.classList.add('resizing');
|
||||
if (editorArea) editorArea.classList.add('resizing');
|
||||
|
||||
document.addEventListener('mousemove', handleConsoleResize);
|
||||
document.addEventListener('mouseup', stopConsoleResize);
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
// Touch support
|
||||
if (sidebarResizer) {
|
||||
sidebarResizer.addEventListener('touchstart', (e) => {
|
||||
isResizingSidebar = true;
|
||||
document.addEventListener('touchmove', handleSidebarResizeTouch);
|
||||
document.addEventListener('touchend', stopSidebarResize);
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
if (consoleResizer) {
|
||||
consoleResizer.addEventListener('touchstart', (e) => {
|
||||
isResizingConsole = true;
|
||||
// Thêm class resizing ngay khi bắt đầu để disable transition
|
||||
const consolePanel = document.querySelector('#console-panel');
|
||||
const editorArea = document.querySelector('#editor-area');
|
||||
if (consolePanel) consolePanel.classList.add('resizing');
|
||||
if (editorArea) editorArea.classList.add('resizing');
|
||||
|
||||
document.addEventListener('touchmove', handleConsoleResizeTouch);
|
||||
document.addEventListener('touchend', stopConsoleResize);
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleSidebarResize(e) {
|
||||
if (!isResizingSidebar) return;
|
||||
|
||||
const container = document.querySelector('.script-editor-container');
|
||||
const sidebar = document.querySelector('.sidebar-container');
|
||||
|
||||
if (!container || !sidebar) return;
|
||||
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
const newWidth = e.clientX - containerRect.left;
|
||||
const minWidth = 200;
|
||||
const maxWidth = Math.min(600, containerRect.width * 0.5);
|
||||
|
||||
if (newWidth >= minWidth && newWidth <= maxWidth) {
|
||||
sidebar.style.width = newWidth + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
function handleSidebarResizeTouch(e) {
|
||||
if (!isResizingSidebar || !e.touches || e.touches.length === 0) return;
|
||||
|
||||
const container = document.querySelector('.script-editor-container');
|
||||
const sidebar = document.querySelector('.sidebar-container');
|
||||
|
||||
if (!container || !sidebar) return;
|
||||
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
const newWidth = e.touches[0].clientX - containerRect.left;
|
||||
const minWidth = 200;
|
||||
const maxWidth = Math.min(600, containerRect.width * 0.5);
|
||||
|
||||
if (newWidth >= minWidth && newWidth <= maxWidth) {
|
||||
sidebar.style.width = newWidth + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
function stopSidebarResize() {
|
||||
isResizingSidebar = false;
|
||||
document.removeEventListener('mousemove', handleSidebarResize);
|
||||
document.removeEventListener('mouseup', stopSidebarResize);
|
||||
document.removeEventListener('touchmove', handleSidebarResizeTouch);
|
||||
document.removeEventListener('touchend', stopSidebarResize);
|
||||
}
|
||||
|
||||
function handleConsoleResize(e) {
|
||||
if (!isResizingConsole) return;
|
||||
|
||||
const container = document.querySelector('.editor-console-container');
|
||||
const editorArea = document.querySelector('#editor-area');
|
||||
const consolePanel = document.querySelector('#console-panel');
|
||||
|
||||
if (!container || !editorArea || !consolePanel) return;
|
||||
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
const containerHeight = containerRect.height;
|
||||
const newConsoleHeight = containerRect.bottom - e.clientY;
|
||||
const minConsoleHeight = 100;
|
||||
const maxConsoleHeight = containerHeight * 0.8;
|
||||
|
||||
if (newConsoleHeight >= minConsoleHeight && newConsoleHeight <= maxConsoleHeight) {
|
||||
const newEditorHeight = containerHeight - newConsoleHeight - 4; // 4px cho resizer
|
||||
editorArea.style.height = newEditorHeight + 'px';
|
||||
consolePanel.style.height = newConsoleHeight + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
function handleConsoleResizeTouch(e) {
|
||||
if (!isResizingConsole || !e.touches || e.touches.length === 0) return;
|
||||
|
||||
const container = document.querySelector('.editor-console-container');
|
||||
const editorArea = document.querySelector('#editor-area');
|
||||
const consolePanel = document.querySelector('#console-panel');
|
||||
|
||||
if (!container || !editorArea || !consolePanel) return;
|
||||
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
const containerHeight = containerRect.height;
|
||||
const newConsoleHeight = containerRect.bottom - e.touches[0].clientY;
|
||||
const minConsoleHeight = 100;
|
||||
const maxConsoleHeight = containerHeight * 0.8;
|
||||
|
||||
if (newConsoleHeight >= minConsoleHeight && newConsoleHeight <= maxConsoleHeight) {
|
||||
const newEditorHeight = containerHeight - newConsoleHeight - 4; // 4px cho resizer
|
||||
editorArea.style.height = newEditorHeight + 'px';
|
||||
consolePanel.style.height = newConsoleHeight + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
function stopConsoleResize() {
|
||||
isResizingConsole = false;
|
||||
|
||||
// Remove resizing class để restore transition
|
||||
const consolePanel = document.querySelector('#console-panel');
|
||||
const editorArea = document.querySelector('#editor-area');
|
||||
if (consolePanel) {
|
||||
consolePanel.classList.remove('resizing');
|
||||
}
|
||||
if (editorArea) {
|
||||
editorArea.classList.remove('resizing');
|
||||
}
|
||||
|
||||
document.removeEventListener('mousemove', handleConsoleResize);
|
||||
document.removeEventListener('mouseup', stopConsoleResize);
|
||||
document.removeEventListener('touchmove', handleConsoleResizeTouch);
|
||||
document.removeEventListener('touchend', stopConsoleResize);
|
||||
}
|
||||
|
||||
export function cleanupLayout() {
|
||||
// Cleanup accordion handlers
|
||||
if (accordionHeaders && accordionHeaders.length > 0) {
|
||||
accordionHeaders.forEach(header => {
|
||||
header.removeEventListener('click', handleAccordionClick);
|
||||
});
|
||||
}
|
||||
accordionHeaders = [];
|
||||
|
||||
// Reset tất cả tabs về trạng thái collapsed
|
||||
const allTabs = document.querySelectorAll('.sidebar-accordion-item');
|
||||
allTabs.forEach(tab => {
|
||||
const header = tab.querySelector('.sidebar-accordion-header');
|
||||
const content = tab.querySelector('.sidebar-accordion-content');
|
||||
const arrow = tab.querySelector('.accordion-arrow');
|
||||
|
||||
if (header && content && arrow) {
|
||||
header.classList.remove('active');
|
||||
content.classList.remove('expanded');
|
||||
content.classList.add('collapsed');
|
||||
arrow.textContent = '▶';
|
||||
}
|
||||
});
|
||||
|
||||
activeTab = null;
|
||||
|
||||
// Cleanup resize handlers
|
||||
stopSidebarResize();
|
||||
stopConsoleResize();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
window.robotnet = window.robotnet || {};
|
||||
robotnet.console = {
|
||||
init: function (dotNetRef) {
|
||||
// Initialization if needed
|
||||
},
|
||||
|
||||
addMessage: function (level, message, autoScroll) {
|
||||
const container = document.getElementById('console-content');
|
||||
if (!container) return;
|
||||
|
||||
const messageDiv = document.createElement('div');
|
||||
messageDiv.className = `console-message console-message-${level.toLowerCase()}`;
|
||||
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
const levelSpan = document.createElement('span');
|
||||
levelSpan.className = 'console-level';
|
||||
levelSpan.textContent = level;
|
||||
|
||||
const timeSpan = document.createElement('span');
|
||||
timeSpan.className = 'console-time';
|
||||
timeSpan.textContent = timestamp;
|
||||
|
||||
const messageSpan = document.createElement('span');
|
||||
messageSpan.className = 'console-text';
|
||||
messageSpan.textContent = message;
|
||||
|
||||
messageDiv.appendChild(levelSpan);
|
||||
messageDiv.appendChild(timeSpan);
|
||||
messageDiv.appendChild(messageSpan);
|
||||
|
||||
container.appendChild(messageDiv);
|
||||
|
||||
if (autoScroll) {
|
||||
container.scrollTop = container.scrollHeight;
|
||||
}
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
const container = document.getElementById('console-content');
|
||||
if (!container) return;
|
||||
|
||||
// Xóa tất cả messages bằng cách set innerHTML rỗng
|
||||
container.innerHTML = '';
|
||||
},
|
||||
|
||||
toggleCollapse: function () {
|
||||
const container = document.getElementById('console-content');
|
||||
const consolePanel = document.getElementById('console-panel');
|
||||
const consoleHeader = document.querySelector('.console-header');
|
||||
const verticalResizer = document.querySelector('.vertical-resizer');
|
||||
const toggleButton = document.querySelector('.console-container .btn-toggle');
|
||||
const iconSpan = toggleButton?.querySelector('span');
|
||||
|
||||
if (!container || !consolePanel || !toggleButton || !iconSpan) return;
|
||||
|
||||
// Check trạng thái hiện tại trước khi toggle
|
||||
const wasCollapsed = container.classList.contains('collapsed');
|
||||
|
||||
// Toggle collapsed class trên cả console-content và console-panel
|
||||
container.classList.toggle('collapsed');
|
||||
consolePanel.classList.toggle('collapsed');
|
||||
|
||||
// Tính toán và set height cho console-panel sau khi toggle
|
||||
if (!wasCollapsed) {
|
||||
// Đang collapse - set height về chỉ còn header
|
||||
if (consoleHeader) {
|
||||
const headerHeight = consoleHeader.offsetHeight;
|
||||
consolePanel.style.height = headerHeight + 'px';
|
||||
} else {
|
||||
consolePanel.style.height = '40px'; // Fallback height
|
||||
}
|
||||
// Ẩn vertical resizer khi collapsed
|
||||
if (verticalResizer) {
|
||||
verticalResizer.style.display = 'none';
|
||||
}
|
||||
// Update icon
|
||||
iconSpan.className = 'mdi mdi-chevron-up';
|
||||
toggleButton.title = 'Expand Console';
|
||||
} else {
|
||||
// Đang expand - restore về height mặc định
|
||||
consolePanel.style.height = '200px';
|
||||
// Hiện vertical resizer khi expanded
|
||||
if (verticalResizer) {
|
||||
verticalResizer.style.display = '';
|
||||
}
|
||||
// Update icon
|
||||
iconSpan.className = 'mdi mdi-chevron-down';
|
||||
toggleButton.title = 'Collapse Console';
|
||||
}
|
||||
}
|
||||
};
|
||||
robotnet.monaco = {
|
||||
CSharpLanguageRegisterSignatureHelpProvider: (dotnetRef, getSignatureHelpMethod) => {
|
||||
return monaco.languages.registerSignatureHelpProvider("csharp", {
|
||||
signatureHelpTriggerCharacters: ['('],
|
||||
provideSignatureHelp: async (model, position, token, context) => {
|
||||
let signature = await dotnetRef.invokeMethodAsync(getSignatureHelpMethod, model.uri.toString(), position.lineNumber, position.column);
|
||||
if (!signature) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
value: signature.value,
|
||||
dispose: () => { },
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
robotnet.blazor = {
|
||||
getResourcePath: function (logicalName) {
|
||||
// In .NET 10, try to get resource path from Blazor runtime
|
||||
// Strategy 1: Try to access via window.Blazor or Blazor._internal
|
||||
if (window.Blazor && window.Blazor._internal) {
|
||||
try {
|
||||
// Try to get resource mapping from Blazor internal APIs
|
||||
var resources = window.Blazor._internal.resources;
|
||||
if (resources && resources.assembly) {
|
||||
var assemblyName = logicalName.replace('.wasm', '');
|
||||
if (resources.assembly[assemblyName]) {
|
||||
return '/_framework/' + resources.assembly[assemblyName];
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Fallback to direct path
|
||||
}
|
||||
}
|
||||
|
||||
// Strategy 2: Try direct path (NET 10+)
|
||||
// In .NET 10, resources might be directly accessible
|
||||
return '/_framework/' + logicalName;
|
||||
}
|
||||
}
|
||||
|
||||
window.fileExplorer = {
|
||||
init: function (element) {
|
||||
// Initialize file explorer interactions
|
||||
// Currently no initialization needed as we use MudMenu for context menus
|
||||
// This function is kept for future use if needed
|
||||
},
|
||||
|
||||
updateFileBadges: function (fileId, showWarning, showError, showModified, warningCount, errorCount, fileName) {
|
||||
if (!fileId) return;
|
||||
|
||||
// Update name
|
||||
const nameElement = document.querySelector(`[data-file-id="${fileId}"][data-name="name"]`);
|
||||
if (nameElement) {
|
||||
nameElement.textContent = fileName;
|
||||
}
|
||||
|
||||
// Update warning badge
|
||||
const warningBadge = document.querySelector(`[data-file-id="${fileId}"][data-badge="warning"]`);
|
||||
if (warningBadge) {
|
||||
warningBadge.textContent = warningCount;
|
||||
warningBadge.setAttribute('data-count', warningCount);
|
||||
warningBadge.setAttribute('title', `${warningCount} warning(s)`);
|
||||
if (showWarning) {
|
||||
warningBadge.classList.remove('hidden');
|
||||
} else {
|
||||
warningBadge.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
// Update error badge
|
||||
const errorBadge = document.querySelector(`[data-file-id="${fileId}"][data-badge="error"]`);
|
||||
if (errorBadge) {
|
||||
errorBadge.textContent = errorCount;
|
||||
errorBadge.setAttribute('data-count', errorCount);
|
||||
errorBadge.setAttribute('title', `${errorCount} error(s)`);
|
||||
if (showError) {
|
||||
errorBadge.classList.remove('hidden');
|
||||
} else {
|
||||
errorBadge.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
// Update modified badge
|
||||
const modifiedBadge = document.querySelector(`[data-file-id="${fileId}"][data-badge="modified"]`);
|
||||
if (modifiedBadge) {
|
||||
if (showModified) {
|
||||
modifiedBadge.classList.remove('hidden');
|
||||
} else {
|
||||
modifiedBadge.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
CheckRadioById: function (id) {
|
||||
const radio = document.getElementById(id);
|
||||
if (radio) {
|
||||
radio.checked = true;
|
||||
// Trigger change event to ensure CSS :has(:checked) selector works
|
||||
radio.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
}
|
||||
},
|
||||
|
||||
UncheckRadioByName: function (name) {
|
||||
const radios = document.querySelectorAll(`input[type="radio"][name="${name}"]`);
|
||||
radios.forEach(radio => radio.checked = false);
|
||||
},
|
||||
|
||||
updateFolderBadges: function (folderPath, showWarning, showError, showModified, warningCount, errorCount, folderName) {
|
||||
if (!folderPath) return;
|
||||
|
||||
// Update name
|
||||
const nameElement = document.querySelector(`[data-folder-path="${folderPath}"][data-name="name"]`);
|
||||
if (nameElement) {
|
||||
nameElement.textContent = folderName;
|
||||
}
|
||||
|
||||
// Update warning badge
|
||||
const warningBadge = document.querySelector(`[data-folder-path="${folderPath}"][data-badge="warning"]`);
|
||||
if (warningBadge) {
|
||||
warningBadge.textContent = warningCount;
|
||||
warningBadge.setAttribute('data-count', warningCount);
|
||||
warningBadge.setAttribute('title', `${warningCount} warning(s)`);
|
||||
if (showWarning) {
|
||||
warningBadge.classList.remove('hidden');
|
||||
} else {
|
||||
warningBadge.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
// Update error badge
|
||||
const errorBadge = document.querySelector(`[data-folder-path="${folderPath}"][data-badge="error"]`);
|
||||
if (errorBadge) {
|
||||
errorBadge.textContent = errorCount;
|
||||
errorBadge.setAttribute('data-count', errorCount);
|
||||
errorBadge.setAttribute('title', `${errorCount} error(s)`);
|
||||
if (showError) {
|
||||
errorBadge.classList.remove('hidden');
|
||||
} else {
|
||||
errorBadge.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
// Update modified badge
|
||||
const modifiedBadge = document.querySelector(`[data-folder-path="${folderPath}"][data-badge="modified"]`);
|
||||
if (modifiedBadge) {
|
||||
if (showModified) {
|
||||
modifiedBadge.classList.remove('hidden');
|
||||
} else {
|
||||
modifiedBadge.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
/* Console Message */
|
||||
.console-message {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 4px 0;
|
||||
word-wrap: break-word;
|
||||
border-left: 3px solid transparent;
|
||||
padding-left: 8px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.console-message:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
/* Console Level Badge */
|
||||
.console-level {
|
||||
font-weight: 600;
|
||||
font-size: 10px;
|
||||
text-transform: uppercase;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
min-width: 50px;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Console Time */
|
||||
.console-time {
|
||||
color: #858585;
|
||||
font-size: 11px;
|
||||
flex-shrink: 0;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
/* Console Text */
|
||||
.console-text {
|
||||
flex: 1;
|
||||
color: #cccccc;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* Message Level Styles */
|
||||
.console-message-info {
|
||||
border-left-color: #007acc;
|
||||
}
|
||||
|
||||
.console-message-info .console-level {
|
||||
background-color: rgba(0, 122, 204, 0.2);
|
||||
color: #4fc3f7;
|
||||
}
|
||||
|
||||
.console-message-warn {
|
||||
border-left-color: #ffa726;
|
||||
}
|
||||
|
||||
.console-message-warn .console-level {
|
||||
background-color: rgba(255, 167, 38, 0.2);
|
||||
color: #ffb74d;
|
||||
}
|
||||
|
||||
.console-message-error {
|
||||
border-left-color: #f44336;
|
||||
}
|
||||
|
||||
.console-message-error .console-level {
|
||||
background-color: rgba(244, 67, 54, 0.2);
|
||||
color: #ef5350;
|
||||
}
|
||||
Reference in New Issue
Block a user