Skip to content

Commit a63a750

Browse files
committed
Add support for local schemas
1 parent 2e85a14 commit a63a750

2 files changed

Lines changed: 88 additions & 28 deletions

File tree

index.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ <h1 class="mb-1">MLB LED Scoreboard Config Editor</h1>
2929
<option value="config-gen-schemas">config-gen-schemas (Testing)</option>
3030
</select>
3131
</div>
32+
<div class="d-flex align-items-center gap-3 mb-3">
33+
<span>Or load local schema:</span>
34+
<input type="file" id="local-schema-input" accept=".json" class="d-none">
35+
<button class="btn btn-outline-secondary btn-sm" id="local-schema-btn">
36+
<i class="bi bi-folder2-open"></i> Choose file...
37+
</button>
38+
<span id="local-schema-name" class="text-secondary small"></span>
39+
</div>
3240

3341
<ul class="nav nav-tabs mb-4" role="tablist">
3442
<li class="nav-item">

src/main.js

Lines changed: 80 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -69,39 +69,45 @@ async function loadEditorData(schemaUrl, exampleUrl) {
6969

7070
// --- Editor initialization ---
7171

72-
function initEditor({ schemaUrl, exampleUrl, containerId, outputId }) {
72+
function createEditor(schema, data, containerId, outputId) {
7373
const container = document.querySelector(`#${containerId}`);
7474
const output = document.querySelector(`#${outputId}`);
7575

76-
loadEditorData(schemaUrl, exampleUrl)
77-
.then(({ schema, data }) => requestAnimationFrame(() => {
78-
container.innerHTML = '';
79-
const jedison = new Jedison.Create({
80-
container,
81-
theme: new Jedison.ThemeBootstrap5(),
82-
iconLib: 'bootstrap-icons',
83-
btnContents: false,
84-
enableCollapseToggle: true,
85-
enablePropertiesToggle: true,
86-
deactivateNonRequired: false,
87-
customEditors: [EditorColorCustom],
88-
schema,
89-
...(data && { data })
90-
});
91-
92-
function updateOutput() {
93-
if (!jedison.getErrors().length) {
94-
output.value = JSON.stringify(jedison.getValue(), null, 2);
95-
output.dataset.valid = 'true';
96-
} else {
97-
output.value = 'Invalid config! Fix errors to see JSON output.';
98-
output.dataset.valid = 'false';
99-
}
76+
requestAnimationFrame(() => {
77+
container.innerHTML = '';
78+
const jedison = new Jedison.Create({
79+
container,
80+
theme: new Jedison.ThemeBootstrap5(),
81+
iconLib: 'bootstrap-icons',
82+
btnContents: false,
83+
enableCollapseToggle: true,
84+
enablePropertiesToggle: true,
85+
deactivateNonRequired: false,
86+
customEditors: [EditorColorCustom],
87+
schema,
88+
...(data && { data })
89+
});
90+
91+
function updateOutput() {
92+
if (!jedison.getErrors().length) {
93+
output.value = JSON.stringify(jedison.getValue(), null, 2);
94+
output.dataset.valid = 'true';
95+
} else {
96+
output.value = 'Invalid config! Fix errors to see JSON output.';
97+
output.dataset.valid = 'false';
10098
}
99+
}
100+
101+
jedison.on('change', updateOutput);
102+
updateOutput();
103+
});
104+
}
105+
106+
function initEditor({ schemaUrl, exampleUrl, containerId, outputId }) {
107+
const container = document.querySelector(`#${containerId}`);
101108

102-
jedison.on('change', updateOutput);
103-
updateOutput();
104-
}))
109+
loadEditorData(schemaUrl, exampleUrl)
110+
.then(({ schema, data }) => createEditor(schema, data, containerId, outputId))
105111
.catch(err => {
106112
container.textContent = `Failed to load schema: ${err.message}`;
107113
});
@@ -206,6 +212,52 @@ async function init() {
206212

207213
init();
208214

215+
// --- Local schema file picker ---
216+
217+
const TAB_EDITOR_MAP = {
218+
'tab-config': { containerId: 'jedison-config', outputId: 'output-config' },
219+
'tab-teams': { containerId: 'jedison-teams', outputId: 'output-teams' },
220+
'tab-scoreboard': { containerId: 'jedison-scoreboard', outputId: 'output-scoreboard' },
221+
'tab-wxhy': { containerId: 'jedison-wxhy', outputId: 'output-wxhy' }
222+
};
223+
224+
const localSchemaInput = document.querySelector('#local-schema-input');
225+
const localSchemaBtn = document.querySelector('#local-schema-btn');
226+
const localSchemaName = document.querySelector('#local-schema-name');
227+
228+
localSchemaBtn.addEventListener('click', () => localSchemaInput.click());
229+
230+
localSchemaInput.addEventListener('change', async () => {
231+
const file = localSchemaInput.files[0];
232+
if (!file) return;
233+
234+
localSchemaName.textContent = file.name;
235+
236+
const activeTabBtn = document.querySelector('.nav-link.active[data-bs-target]');
237+
const tabId = activeTabBtn?.dataset.bsTarget?.slice(1);
238+
const editorConfig = TAB_EDITOR_MAP[tabId];
239+
if (!editorConfig) return;
240+
241+
const { containerId, outputId } = editorConfig;
242+
const container = document.querySelector(`#${containerId}`);
243+
container.innerHTML = '<div class="loader"></div>';
244+
245+
try {
246+
const text = await file.text();
247+
const schema = JSON.parse(text);
248+
249+
const refParser = new Jedison.RefParser();
250+
await refParser.dereference(schema);
251+
refParser.expandRecursive(schema);
252+
253+
createEditor(schema, null, containerId, outputId);
254+
} catch (err) {
255+
container.textContent = `Failed to load local schema: ${err.message}`;
256+
}
257+
258+
localSchemaInput.value = '';
259+
});
260+
209261
// --- Copy buttons ---
210262

211263
document.querySelectorAll('.copy-btn').forEach(btn => {

0 commit comments

Comments
 (0)