systemprompt-mcp 0.1.0

Core MCP (Model Context Protocol) functionality for systemprompt.io OS
Documentation
const TableApp = {
    columns: window.TABLE_COLUMNS,
    rows: window.TABLE_ROWS,
    sortableColumns: window.TABLE_SORTABLE,
    filterable: window.TABLE_FILTERABLE,
    pageSize: window.TABLE_PAGE_SIZE,
    currentPage: 1,
    sortColumn: null,
    sortDirection: 'asc',
    filterText: '',

    init() {
        this.renderHeader();
        this.renderBody();
        this.setupEventListeners();
        if (this.pageSize > 0) this.renderPagination();
    },

    renderHeader() {
        const thead = document.getElementById('table-head');
        const tr = document.createElement('tr');
        this.columns.forEach((col, i) => {
            const th = document.createElement('th');
            th.textContent = col;
            th.dataset.index = i;
            if (this.sortableColumns.includes(col)) {
                th.classList.add('sortable');
                th.addEventListener('click', () => this.sort(i));
            }
            tr.appendChild(th);
        });
        thead.appendChild(tr);
    },

    renderBody() {
        const tbody = document.getElementById('table-body');
        tbody.innerHTML = '';

        let data = this.getFilteredData();
        if (this.pageSize > 0) {
            const start = (this.currentPage - 1) * this.pageSize;
            data = data.slice(start, start + this.pageSize);
        }

        data.forEach(row => {
            const tr = document.createElement('tr');
            row.forEach(cell => {
                const td = document.createElement('td');
                td.textContent = cell === null ? '' : String(cell);
                tr.appendChild(td);
            });
            tbody.appendChild(tr);
        });
    },

    getFilteredData() {
        if (!this.filterText) return [...this.rows];
        const lower = this.filterText.toLowerCase();
        return this.rows.filter(row =>
            row.some(cell => String(cell).toLowerCase().includes(lower))
        );
    },

    sort(colIndex) {
        if (this.sortColumn === colIndex) {
            this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
        } else {
            this.sortColumn = colIndex;
            this.sortDirection = 'asc';
        }

        this.rows.sort((a, b) => {
            const aVal = a[colIndex];
            const bVal = b[colIndex];
            const cmp = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
            return this.sortDirection === 'asc' ? cmp : -cmp;
        });

        this.currentPage = 1;
        this.renderBody();
        this.updateSortIndicators();
        if (this.pageSize > 0) this.renderPagination();
    },

    updateSortIndicators() {
        document.querySelectorAll('th.sortable').forEach(th => {
            th.classList.remove('sort-asc', 'sort-desc');
            if (parseInt(th.dataset.index) === this.sortColumn) {
                th.classList.add(this.sortDirection === 'asc' ? 'sort-asc' : 'sort-desc');
            }
        });
    },

    setupEventListeners() {
        if (this.filterable) {
            const input = document.getElementById('filter-input');
            if (input) {
                input.addEventListener('input', (e) => {
                    this.filterText = e.target.value;
                    this.currentPage = 1;
                    this.renderBody();
                    if (this.pageSize > 0) this.renderPagination();
                });
            }
        }
    },

    renderPagination() {
        const container = document.getElementById('pagination');
        if (!container) return;

        const filtered = this.getFilteredData();
        const totalPages = Math.ceil(filtered.length / this.pageSize);

        container.innerHTML = '';

        const info = document.createElement('span');
        info.className = 'page-info';
        info.textContent = `Page ${this.currentPage} of ${totalPages} (${filtered.length} rows)`;
        container.appendChild(info);

        const nav = document.createElement('div');
        nav.className = 'page-nav';

        const prevBtn = document.createElement('button');
        prevBtn.textContent = 'Previous';
        prevBtn.disabled = this.currentPage === 1;
        prevBtn.addEventListener('click', () => { this.currentPage--; this.renderBody(); this.renderPagination(); });
        nav.appendChild(prevBtn);

        const nextBtn = document.createElement('button');
        nextBtn.textContent = 'Next';
        nextBtn.disabled = this.currentPage >= totalPages;
        nextBtn.addEventListener('click', () => { this.currentPage++; this.renderBody(); this.renderPagination(); });
        nav.appendChild(nextBtn);

        container.appendChild(nav);
    }
};

document.addEventListener('DOMContentLoaded', () => TableApp.init());