@etm-professional-control/winccoa-mcp-server
Version:
MCP Server for WinCC OA with field-specific configurations
408 lines • 11.9 kB
JavaScript
/**
* Icon List Manager
*
* Manages the 1,407 Siemens IX icons available for WinCC OA dashboards.
* Provides categorization, searching, and filtering capabilities.
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
// ES module equivalent of __dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
/**
* Icon categories with curated icon lists
*/
export const ICON_CATEGORIES = [
{
name: 'trend',
description: 'Trend and direction indicators',
keywords: ['trend', 'direction', 'up', 'down', 'sideways'],
icons: [
'trend',
'trend-upward',
'trend-upward-filled',
'trend-upward-circle',
'trend-downward',
'trend-downward-filled',
'trend-downward-circle',
'trend-sideways',
'trend-sideways-filled',
'trend-sideways-circle',
'trend-companion',
'trend-flat-curve',
'monitor-trend'
]
},
{
name: 'chart',
description: 'Chart and graph types',
keywords: ['chart', 'graph', 'diagram', 'plot', 'visualization'],
icons: [
'chart-curve-spline',
'chart-curve-linear',
'chart-curve-stepped',
'barchart',
'barchart-horizontal',
'stacked-barchart',
'linechart',
'areachart',
'piechart',
'piechart-filled',
'doughnutchart',
'doughnutchart-filled',
'radarchart',
'polarchart',
'polarchart-filled',
'spiderchart',
'spiderchart-filled',
'gaugechart',
'gauge',
'gauge-filled',
'ganttchart',
'sankeychart',
'scatterplot',
'box-plot',
'box-plot-filled',
'heat-map-chart',
'heat-map-chart-filled',
'chart-diagram',
'chart-diagrams'
]
},
{
name: 'status',
description: 'Status indicators and alerts',
keywords: ['status', 'alert', 'alarm', 'error', 'warning', 'success', 'info'],
icons: [
'alarm',
'alarm-filled',
'error',
'error-filled',
'warning',
'warning-filled',
'warning-rhomb',
'warning-rhomb-filled',
'warning-hexagon',
'warning-hexagon-filled',
'warning-octagon',
'warning-octagon-filled',
'warning-square',
'warning-square-filled',
'success',
'success-filled',
'info',
'info-filled',
'indicator',
'indicator-filled'
]
},
{
name: 'action',
description: 'Common user actions',
keywords: ['action', 'edit', 'delete', 'save', 'download', 'upload', 'copy'],
icons: [
'pen',
'pen-filled',
'trashcan',
'trashcan-filled',
'download',
'upload',
'save',
'save-all',
'refresh',
'reload',
'copy',
'copy-filled',
'paste',
'paste-filled',
'cut',
'cut-filled',
'add',
'minus',
'check',
'close',
'cancel'
]
},
{
name: 'navigation',
description: 'Navigation and movement',
keywords: ['navigation', 'arrow', 'chevron', 'home', 'search'],
icons: [
'home',
'home-filled',
'search',
'chevron-up',
'chevron-down',
'chevron-left',
'chevron-right',
'chevron-up-small',
'chevron-down-small',
'arrow-up',
'arrow-down',
'arrow-left',
'arrow-right',
'double-chevron-up',
'double-chevron-down',
'double-chevron-left',
'double-chevron-right'
]
},
{
name: 'settings',
description: 'Configuration and settings',
keywords: ['settings', 'configuration', 'cogwheel', 'gear'],
icons: [
'cogwheel',
'cogwheel-filled',
'configuration',
'settings',
'user-settings',
'user-settings-filled',
'user-management-settings',
'project-settings',
'calendar-settings',
'database',
'database-filled'
]
},
{
name: 'time',
description: 'Time and schedule related',
keywords: ['time', 'clock', 'calendar', 'schedule', 'date'],
icons: [
'clock',
'clock-filled',
'calendar',
'calendar-filled',
'calendar-day',
'calendar-week',
'hourglass',
'hourglass-filled',
'stopwatch',
'stopwatch-filled',
'alarm-clock',
'alarm-clock-filled',
'time-zone',
'time-zone-filled'
]
},
{
name: 'device',
description: 'Hardware and devices',
keywords: ['device', 'hardware', 'plc', 'network', 'sensor'],
icons: [
'generic-device',
'plc-device',
'plc',
'network-device',
'network-device-filled',
'server-interface',
'pc-tower',
'monitor',
'screen',
'sensor',
'drive',
'power-supply'
]
},
{
name: 'user',
description: 'People and user management',
keywords: ['user', 'person', 'people', 'profile', 'group'],
icons: [
'user',
'user-filled',
'user-profile',
'user-profile-filled',
'user-group',
'user-management',
'user-management-filled',
'add-user'
]
},
{
name: 'file',
description: 'Files and documents',
keywords: ['file', 'document', 'folder', 'pdf', 'save'],
icons: [
'document',
'document-filled',
'folder',
'folder-filled',
'folder-open',
'folder-new',
'open-file',
'pdf-document',
'code-document',
'text-document',
'json-document',
'xml-document'
]
},
{
name: 'plant',
description: 'Industrial plants and buildings',
keywords: ['plant', 'factory', 'building', 'industrial'],
icons: [
'plant',
'plant-filled',
'plant-details',
'create-plant',
'operate-plant',
'building1',
'building2',
'global-plant'
]
},
{
name: 'battery',
description: 'Battery and power status',
keywords: ['battery', 'power', 'energy', 'charge', 'voltage'],
icons: [
'battery-full',
'battery-three-quarter',
'battery-half',
'battery-quarter',
'battery-low',
'battery-empty',
'battery-charge',
'electrical-energy'
]
},
{
name: 'network',
description: 'Connectivity and network',
keywords: ['network', 'connection', 'connected', 'wifi', 'signal'],
icons: [
'connected',
'connected-circle',
'disconnected',
'disconnected-circle',
'network-wired',
'network-wired-wireless',
'wlan-strength0',
'wlan-strength1',
'wlan-strength2',
'wlan-strength3'
]
}
];
/**
* Icon List Manager Class
*/
export class IconList {
constructor(projectPath) {
this.allIcons = new Set();
// Path to IX_ICONS_LIST.txt in docs folder
// __dirname points to build/helpers/icons/, so go up 3 levels to reach mcpWinCCOA root
this.iconListPath = projectPath
? path.join(projectPath, 'docs', 'IX_ICONS_LIST.txt')
: path.join(__dirname, '..', '..', '..', 'docs', 'IX_ICONS_LIST.txt');
}
/**
* Load all icons from IX_ICONS_LIST.txt
*/
loadIcons() {
if (this.allIcons.size > 0) {
return; // Already loaded
}
try {
if (fs.existsSync(this.iconListPath)) {
const content = fs.readFileSync(this.iconListPath, 'utf8');
const icons = content.split('\n').map(line => line.trim()).filter(line => line.length > 0);
icons.forEach(icon => this.allIcons.add(icon));
}
else {
// Fallback: load from categories if file doesn't exist
ICON_CATEGORIES.forEach(category => {
category.icons.forEach(icon => this.allIcons.add(icon));
});
}
}
catch (error) {
console.error('Failed to load icon list:', error);
// Fallback to categories
ICON_CATEGORIES.forEach(category => {
category.icons.forEach(icon => this.allIcons.add(icon));
});
}
}
/**
* Search icons by keyword
* @param keyword - Search term (case-insensitive)
* @param limit - Maximum number of results
* @returns Array of matching icon names
*/
searchIcons(keyword, limit = 50) {
this.loadIcons();
if (!keyword || keyword.trim() === '') {
// Return random sample if no keyword
return Array.from(this.allIcons).slice(0, limit);
}
const searchTerm = keyword.toLowerCase();
const matches = [];
for (const icon of this.allIcons) {
if (icon.includes(searchTerm)) {
matches.push(icon);
if (matches.length >= limit) {
break;
}
}
}
return matches.sort();
}
/**
* Get icons for a specific category
* @param categoryName - Category name
* @returns Array of icon names in that category
*/
getCategory(categoryName) {
const category = ICON_CATEGORIES.find(cat => cat.name === categoryName);
return category ? category.icons : [];
}
/**
* Get all available categories
* @returns Array of category information
*/
getAllCategories() {
return ICON_CATEGORIES;
}
/**
* Check if an icon exists
* @param iconName - Icon name to check
* @returns True if icon exists
*/
iconExists(iconName) {
this.loadIcons();
return this.allIcons.has(iconName);
}
/**
* Get total number of icons
* @returns Total icon count
*/
getTotalCount() {
this.loadIcons();
return this.allIcons.size;
}
/**
* Search icons by category and keyword
* @param category - Category name
* @param keyword - Optional search term
* @param limit - Maximum results
* @returns Filtered icon names
*/
searchByCategory(category, keyword, limit = 50) {
const categoryIcons = this.getCategory(category);
if (!keyword || keyword.trim() === '') {
return categoryIcons.slice(0, limit);
}
const searchTerm = keyword.toLowerCase();
return categoryIcons
.filter(icon => icon.includes(searchTerm))
.slice(0, limit);
}
}
//# sourceMappingURL=IconList.js.map