JSON Github - Preview with Editor


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JSON Data Table and Editor</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/9.5.6/jsoneditor.min.css">
    <style>
        #editor {
            width: 100%;
            height: 80vh;
        }
        #successMessage {
            display: none;
            color: green;
            margin-bottom: 10px;
        }
    </style>
</head>
<body>
<div class="container mt-5">
    <h2 class="mb-4">JSON Data Table and Editor</h2>

    <!-- File Links -->
    <div class="row" id="fileLinks">
        <!-- Links will be populated dynamically -->
    </div>

    <!-- Nav pills -->
    <ul class="nav nav-pills mb-3 mt-3" id="pills-tab" role="tablist">
        <li class="nav-item" role="presentation">
            <a class="nav-link active" id="pills-show-tab" data-toggle="pill" href="#pills-show" role="tab" aria-controls="pills-show" aria-selected="true">Show Data</a>
        </li>
        <li class="nav-item" role="presentation">
            <a class="nav-link" id="pills-edit-tab" data-toggle="pill" href="#pills-edit" role="tab" aria-controls="pills-edit" aria-selected="false">Edit Data</a>
        </li>
    </ul>

    <!-- Tab content -->
    <div class="tab-content" id="pills-tabContent">
        <!-- Show Data Tab -->
        <div class="tab-pane fade show active" id="pills-show" role="tabpanel" aria-labelledby="pills-show-tab">
            <div id="jsonTable" class="mt-3"></div>
        </div>

        <!-- Edit Data Tab -->
        <div class="tab-pane fade" id="pills-edit" role="tabpanel" aria-labelledby="pills-edit-tab">
            <label for="editorMode">Editor Mode:</label>
            <select id="editorMode" onchange="changeEditorMode()">
                <option value="tree">Tree</option>
                <option value="text">Text</option>
            </select>

            <div id="editor" class="mt-3"></div>
            <div id="successMessage">Changes saved successfully!</div>
            <button class="btn btn-primary mt-3" onclick="saveChanges()">Save Changes</button>
        </div>
    </div>
</div>

<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/9.5.6/jsoneditor.min.js"></script>
<script>
    const token = 'ghp_xxx'; // Ganti dengan token GitHub Anda
    const owner = 'konokae';
    const repo = 'sl';
    const branch = 'main';

    let editor = null;

    async function fetchRepoContents(path = '') {
        const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${branch}`, {
            headers: {
                'Authorization': `token ${token}`
            }
        });
        return await response.json();
    }

    async function populateFileLinks() {
        const contents = await fetchRepoContents('datatheme');
        const fileLinksDiv = document.getElementById('fileLinks');
        fileLinksDiv.innerHTML = ''; // Clear previous links

        let fileCount = 1; // Initialize file counter starting from 1
        let columnCount = 0;
        let column = document.createElement('div');
        column.className = 'col-md-4';

        contents.forEach(item => {
            if (item.type === 'file' && item.name.endsWith('.json')) {
                const link = document.createElement('a');
                link.href = '#';
                link.className = 'd-block';
                link.textContent = `${fileCount}: ${item.name}`; // Display with the file count
                link.setAttribute('data-filepath', item.path);
                link.onclick = function() {
                    loadSelectedFile(item.path);
                };

                column.appendChild(link);
                fileCount++; // Increment file counter

                if (fileCount % 5 === 1) {
                    fileLinksDiv.appendChild(column);
                    column = document.createElement('div');
                    column.className = 'col-md-4';
                }
            }
        });

        if (column.children.length > 0) {
            fileLinksDiv.appendChild(column);
        }
    }

    async function fetchJson(path) {
        const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${branch}`, {
            headers: {
                'Authorization': `token ${token}`
            }
        });
        const data = await response.json();
        const content = atob(data.content);
        return JSON.parse(content);
    }

    async function saveChanges() {
        const newContent = editor.get();
        const encodedContent = btoa(JSON.stringify(newContent, null, 2));
        const filePath = document.querySelector('.nav-link.active').getAttribute('data-filepath');

        // Get the current file SHA for updating
        const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/${filePath}?ref=${branch}`, {
            headers: {
                'Authorization': `token ${token}`
            }
        });
        const data = await response.json();
        const sha = data.sha;

        // Update the file
        await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/${filePath}`, {
            method: 'PUT',
            headers: {
                'Authorization': `token ${token}`,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                message: 'Updated JSON file via JSON editor',
                content: encodedContent,
                sha: sha,
                branch: branch
            })
        });

        showSuccessMessage();
    }

    function showSuccessMessage() {
        const successMessage = document.getElementById('successMessage');
        successMessage.style.display = 'block';
        setTimeout(() => {
            successMessage.style.display = 'none';
        }, 3000);
    }

    function changeEditorMode() {
        const mode = document.getElementById('editorMode').value;
        const content = editor.get();
        editor.destroy();
        editor = new JSONEditor(document.getElementById('editor'), { mode: mode });
        editor.set(content);
    }

    async function loadSelectedFile(filePath) {
        if (filePath) {
            if (editor) {
                editor.destroy();
            }
            const mode = document.getElementById('editorMode').value;
            editor = new JSONEditor(document.getElementById('editor'), { mode: mode });
            const jsonContent = await fetchJson(filePath);
            editor.set(jsonContent);

            // Load data in show data tab
            loadSelectedFileShow(filePath);
        }
    }

    async function loadSelectedFileShow(filePath) {
        if (filePath) {
            const jsonContent = await fetchJson(filePath);
            const table = document.createElement('table');
            table.className = 'table table-striped';
            const thead = document.createElement('thead');
            const tbody = document.createElement('tbody');

            // Create table header
            const headerRow = document.createElement('tr');
            Object.keys(jsonContent[0]).forEach(key => {
                const th = document.createElement('th');
                th.textContent = key;
                headerRow.appendChild(th);
            });
            thead.appendChild(headerRow);

            // Create table body
            jsonContent.forEach(item => {
                const row = document.createElement('tr');
                Object.values(item).forEach(value => {
                    const td = document.createElement('td');
                    td.textContent = value;
                    row.appendChild(td);
                });
                tbody.appendChild(row);
            });

            table.appendChild(thead);
            table.appendChild(tbody);

            const jsonTableDiv = document.getElementById('jsonTable');
            jsonTableDiv.innerHTML = ''; // Clear previous table
            jsonTableDiv.appendChild(table);
        }
    }

    document.addEventListener('DOMContentLoaded', async () => {
        document.getElementById('editorMode').value = 'tree'; // Set default mode to tree
        editor = new JSONEditor(document.getElementById('editor'), { mode: 'tree' });
        await populateFileLinks();
        // Load the first file initially
        const firstLink = document.querySelector('#fileLinks a');
        if (firstLink) {
            loadSelectedFile(firstLink.getAttribute('data-filepath'));
        }
    });
</script>
</body>
</html>
Audio Title
0:00 / 0:00
Next Post Previous Post