File size: 8,753 Bytes
c001f24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
{% extends "base.html" %}

{% block title %}Upload JSON{% endblock %}

{% block head %}
<script>
MathJax = {
  tex: {
    inlineMath: [['\(', '\)']]
  },
  svg: {
    fontCache: 'global'
  }
};
</script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
{% endblock %}

{% block content %}
<div class="container mt-5">
    <div class="card bg-dark text-white">
        <div class="card-header">
            <h2>Upload JSON Data</h2>
        </div>
        <div class="card-body">
            <form id="json-upload-form">
                <div class="mb-3">
                    <label for="json-data" class="form-label">Paste your JSON data here:</label>
                    <textarea class="form-control" id="json-data" rows="15" required></textarea>
                </div>
                <div class="mb-3">
                    <label class="form-label">Process Questions with Status:</label>
                    <div class="form-check">
                        <input class="form-check-input" type="checkbox" value="correct" id="status_correct">
                        <label class="form-check-label" for="status_correct">
                            Correct
                        </label>
                    </div>
                    <div class="form-check">
                        <input class="form-check-input" type="checkbox" value="wrong" id="status_wrong" checked>
                        <label class="form-check-label" for="status_wrong">
                            Wrong
                        </label>
                    </div>
                    <div class="form-check">
                        <input class="form-check-input" type="checkbox" value="unattempted" id="status_unattempted" checked>
                        <label class="form-check-label" for="status_unattempted">
                            Unattempted
                        </label>
                    </div>
                </div>
                <button type="submit" class="btn btn-primary">Process JSON</button>
            </form>
            <div id="status" class="mt-3"></div>
        </div>
    </div>
</div>
{% endblock %}

{% block scripts %}
<script>
// Function to fix font-family declarations in HTML strings
function fixFontFamilyQuotes(htmlString) {
    // First, handle escaped quotes in the HTML
    // This regex matches font-family declarations with escaped quotes
    htmlString = htmlString.replace(/font-family:\\?"([^\\]+(?:\\.[^\\]*)*)"(?=[\s;>])/g, function(match, fontValue) {
        // Unescape the font value
        let unescapedValue = fontValue.replace(/\\"/g, '"');
        // Replace double quotes with single quotes in the font names
        let fixedValue = unescapedValue.replace(/"/g, "'");
        return `font-family:'${fixedValue}'`;
    });
    
    // Also handle non-escaped font-family declarations
    htmlString = htmlString.replace(/font-family:\s*"([^"]+(?:,\s*"[^"]+"\s*)*)"(?=[\s;>])/g, function(match) {
        // Extract the full font-family value including all fonts
        let fontDeclaration = match.match(/font-family:\s*(.+)/)[1];
        // Replace outer quotes and inner quotes appropriately
        fontDeclaration = fontDeclaration.replace(/^"|"$/g, "'");
        fontDeclaration = fontDeclaration.replace(/","/g, "','");
        return `font-family:${fontDeclaration}`;
    });
    
    // Handle a more complex pattern where font-family might span multiple quoted sections
    htmlString = htmlString.replace(/style="([^"]*)"/g, function(match, styleContent) {
        // Process font-family within style attributes
        let fixedStyle = styleContent.replace(/font-family:([^;]+)(;|$)/g, function(m, fontValue, ending) {
            // Clean up the font value
            fontValue = fontValue.trim();
            
            // If it starts and ends with quotes, process it
            if ((fontValue.startsWith('"') && fontValue.endsWith('"')) || 
                (fontValue.startsWith("'") && fontValue.endsWith("'"))) {
                // Remove outer quotes
                fontValue = fontValue.slice(1, -1);
                // Replace any internal double quotes with single quotes
                fontValue = fontValue.replace(/"/g, "'");
                return `font-family:'${fontValue}'${ending}`;
            }
            
            return m; // Return unchanged if doesn't match pattern
        });
        
        return `style="${fixedStyle}"`;
    });
    
    return htmlString;
}

document.getElementById('json-upload-form').addEventListener('submit', async (e) => {
    e.preventDefault();
    let jsonData = document.getElementById('json-data').value;
    const statusDiv = document.getElementById('status');
    const cardBody = document.querySelector('.card-body');
    const selectedStatuses = Array.from(document.querySelectorAll('input[type="checkbox"][id^="status_"]:checked')).map(cb => cb.value);

    try {
        jsonData = fixFontFamilyQuotes(jsonData);
        const data = JSON.parse(jsonData);
        
        let testName;
        let bodyPayload;
        let endpoint;

        if (data.version && String(data.version) === "2.1") {
            testName = data.test_name;
            bodyPayload = data;
            endpoint = '/json_upload'; 
        } else if (data.data && data.data.root) {
            testName = data.data.root._testAttempt4d9rq8.test.name;
            bodyPayload = { data: data, statuses: selectedStatuses };
            endpoint = '/process_json';
        } else {
            if (data.test_name) {
                testName = data.test_name;
                bodyPayload = data;
                endpoint = '/json_upload';
            } else {
                throw new Error("Unknown JSON format. Could not determine structure.");
            }
        }

        statusDiv.innerHTML = '<div class="alert alert-info">Processing JSON...</div>';
        
        const response = await fetch(endpoint, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(bodyPayload)
        });

        const result = await response.json();

        if (result.success) {
            if (result.edit_url) {
                window.location.href = result.edit_url;
                return;
            }

            const form = document.createElement('form');
            form.action = '/save_processed_json';
            form.method = 'post';

            const questionsInput = document.createElement('input');
            questionsInput.type = 'hidden';
            questionsInput.name = 'questions_data';
            questionsInput.value = JSON.stringify(result.questions);
            form.appendChild(questionsInput);

            const testNameInput = document.createElement('input');
            testNameInput.type = 'hidden';
            testNameInput.name = 'test_name';
            testNameInput.value = testName;
            form.appendChild(testNameInput);

            const table = document.createElement('table');
            table.className = 'table table-dark';
            const thead = document.createElement('thead');
            thead.innerHTML = '<tr><th>Question</th><th>Your Answer</th><th>Correct Answer</th><th>Status</th></tr>';
            table.appendChild(thead);

            const tbody = document.createElement('tbody');
            result.questions.forEach(q => {
                let badgeClass = 'bg-warning text-dark';
                if (q.status === 'wrong') badgeClass = 'bg-danger';
                if (q.status === 'correct') badgeClass = 'bg-success';
                const row = document.createElement('tr');
                row.innerHTML = `<td>${q.question}</td><td>${q.yourAnswer}</td><td>${q.correctAnswer}</td><td><span class="badge ${badgeClass}">${q.status}</span></td>`;
                tbody.appendChild(row);
            });
            table.appendChild(tbody);
            form.appendChild(table);

            const button = document.createElement('button');
            button.type = 'submit';
            button.className = 'btn btn-primary mt-3';
            button.textContent = 'Save and Go to Question Entry';
            form.appendChild(button);

            cardBody.innerHTML = '';
            cardBody.appendChild(form);

            if (window.MathJax) {
                MathJax.typesetPromise();
            }
        } else {
            statusDiv.innerHTML = `<div class="alert alert-danger">Error: ${result.error}</div>`;
        }
    } catch (error) {
        statusDiv.innerHTML = `<div class="alert alert-danger">Invalid JSON format or processing error: ${error.message}</div>`;
    }
});
</script>
{% endblock %}