From ac10c3f541dd90a7bae0ba846062d741f4ea4f24 Mon Sep 17 00:00:00 2001 From: Misode Date: Wed, 23 Jun 2021 23:12:35 +0200 Subject: [PATCH] Fix some errors and make others visible --- src/app/Locales.ts | 2 +- src/app/Schemas.ts | 34 +++++++++++-------- src/app/components/Ad.tsx | 4 ++- src/app/components/ErrorPanel.tsx | 6 ++++ src/app/components/PreviewPanel.tsx | 1 + src/app/components/SourcePanel.tsx | 15 ++++++--- src/app/components/Tree.tsx | 37 +++++++++++--------- src/app/components/index.ts | 1 + src/app/pages/Generator.tsx | 43 +++++++++++++++--------- src/styles/global.css | 52 +++++++++-------------------- 10 files changed, 108 insertions(+), 87 deletions(-) create mode 100644 src/app/components/ErrorPanel.tsx diff --git a/src/app/Locales.ts b/src/app/Locales.ts index 03e4e947..2aee9f80 100644 --- a/src/app/Locales.ts +++ b/src/app/Locales.ts @@ -32,5 +32,5 @@ export async function loadLocale(language: string) { const data = await import(`../locales/${language}.json`) const schema = langConfig.schemas !== false && await import(`../../node_modules/@mcschema/locales/src/${language}.json`) - Locales[language] = { ...data, ...schema, ...data.default, ...schema.default } + Locales[language] = { ...data.default, ...schema.default } } diff --git a/src/app/Schemas.ts b/src/app/Schemas.ts index 41948d22..e51519a4 100644 --- a/src/app/Schemas.ts +++ b/src/app/Schemas.ts @@ -46,11 +46,15 @@ const versionGetter: { async function getVersion(id: VersionId): Promise { if (!Versions[id]) { - const collections = versionGetter[id].getCollections() - const blockStates: BlockStateRegistry = {} - await fetchData(id, collections, blockStates) - const schemas = versionGetter[id].getSchemas(collections) - Versions[id] = { collections, schemas, blockStates } + try { + const collections = versionGetter[id].getCollections() + const blockStates: BlockStateRegistry = {} + await fetchData(id, collections, blockStates) + const schemas = versionGetter[id].getSchemas(collections) + Versions[id] = { collections, schemas, blockStates } + } catch (e) { + throw new Error(`Cannot get version "${id}": ${e.message}`) + } } return Versions[id] } @@ -62,15 +66,19 @@ export async function getModel(version: VersionId, id: string): Promise { document.getElementById('ad-placeholder')?.remove() - ethicalads?.load() + if ('ethicalads' in window) { + ethicalads.load() + } }, []) return
diff --git a/src/app/components/ErrorPanel.tsx b/src/app/components/ErrorPanel.tsx new file mode 100644 index 00000000..e04c84b8 --- /dev/null +++ b/src/app/components/ErrorPanel.tsx @@ -0,0 +1,6 @@ +export function ErrorPanel({ error }: { error: string }) { + return
+

{error}

+

You can report this as a bug on GitHub

+
+} diff --git a/src/app/components/PreviewPanel.tsx b/src/app/components/PreviewPanel.tsx index d81e86cf..9dc23491 100644 --- a/src/app/components/PreviewPanel.tsx +++ b/src/app/components/PreviewPanel.tsx @@ -50,6 +50,7 @@ type PreviewProps = { version: VersionId, id: string, shown: boolean, + onError: (message: string) => unknown, } export function PreviewPanel({ lang, model, version, id, shown }: PreviewProps) { const [, setCount] = useState(0) diff --git a/src/app/components/SourcePanel.tsx b/src/app/components/SourcePanel.tsx index 0e93d5fc..d8eb012a 100644 --- a/src/app/components/SourcePanel.tsx +++ b/src/app/components/SourcePanel.tsx @@ -12,15 +12,22 @@ type SourcePanelProps = { doCopy?: number, doDownload?: number, doImport?: number, + onError: (message: string) => unknown, } -export function SourcePanel({ lang, name, model, doCopy, doDownload, doImport }: SourcePanelProps) { +export function SourcePanel({ lang, name, model, doCopy, doDownload, doImport, onError }: SourcePanelProps) { const loc = locale.bind(null, lang) const source = useRef(null) const download = useRef(null) - + useModel(model, model => { - const data = model.schema.hook(transformOutput, new ModelPath(model), model.data) - source.current.value = JSON.stringify(data, null, 2) + '\n' + try { + const data = model.schema.hook(transformOutput, new ModelPath(model), model.data) + source.current.value = JSON.stringify(data, null, 2) + '\n' + } catch (e) { + onError(`Error getting JSON output: ${e.message}`) + console.error(e) + source.current.value = '' + } }) const onImport = () => { diff --git a/src/app/components/Tree.tsx b/src/app/components/Tree.tsx index 8015ed7c..27137f74 100644 --- a/src/app/components/Tree.tsx +++ b/src/app/components/Tree.tsx @@ -11,29 +11,36 @@ type TreePanelProps = { lang: string, model: DataModel | null, version: VersionId, + onError: (message: string) => unknown, } -export function Tree({ lang, model, version }: TreePanelProps) { +export function Tree({ lang, model, version, onError }: TreePanelProps) { const tree = useRef(null) const redraw = useRef() useEffect(() => { redraw.current = () => { if (!model) return - const mounter = new Mounter() - const props = { loc: locale.bind(null, lang), version, mounter } - const path = new ModelPath(model) - const rendered = model.schema.hook(renderHtml, path, model.data, props) - const category = model.schema.category(path) - const type = model.schema.type(path) - let html = rendered[2] - if (rendered[1]) { - html = `
-
${rendered[1]}
-
${rendered[2]}
-
` + try { + const mounter = new Mounter() + const props = { loc: locale.bind(null, lang), version, mounter } + const path = new ModelPath(model) + const rendered = model.schema.hook(renderHtml, path, model.data, props) + const category = model.schema.category(path) + const type = model.schema.type(path) + let html = rendered[2] + if (rendered[1]) { + html = `
+
${rendered[1]}
+
${rendered[2]}
+
` + } + tree.current.innerHTML = html + mounter.mounted(tree.current) + } catch (e) { + onError(`Error rendering the tree: ${e.message}`) + console.error(e) + tree.current.innerHTML = '' } - tree.current.innerHTML = html - mounter.mounted(tree.current) } }) diff --git a/src/app/components/index.ts b/src/app/components/index.ts index 69c566de..2b1c7c05 100644 --- a/src/app/components/index.ts +++ b/src/app/components/index.ts @@ -2,6 +2,7 @@ export * from './Ad' export * from './Btn' export * from './BtnInput' export * from './BtnMenu' +export * from './ErrorPanel' export * from './Header' export * from './Octicon' export * from './PreviewPanel' diff --git a/src/app/pages/Generator.tsx b/src/app/pages/Generator.tsx index f1f3ed3b..e09229e9 100644 --- a/src/app/pages/Generator.tsx +++ b/src/app/pages/Generator.tsx @@ -1,8 +1,8 @@ import type { DataModel } from '@mcschema/core' -import { useEffect, useState } from 'preact/hooks' +import { useEffect, useErrorBoundary, useState } from 'preact/hooks' import config from '../../config.json' import { Analytics } from '../Analytics' -import { Ad, Btn, BtnInput, BtnMenu, HasPreview, Octicon, PreviewPanel, SourcePanel, Tree } from '../components' +import { Ad, Btn, BtnInput, BtnMenu, ErrorPanel, HasPreview, Octicon, PreviewPanel, SourcePanel, Tree } from '../components' import { fetchPreset } from '../DataFetcher' import { locale } from '../Locales' import type { VersionId } from '../Schemas' @@ -19,11 +19,17 @@ type GeneratorProps = { } export function Generator({ lang, changeTitle, version, onChangeVersion, category, generator }: GeneratorProps) { const loc = locale.bind(null, lang) + const [error, setError] = useState('') + const [errorBoundary] = useErrorBoundary() + if (errorBoundary) { + return
+ } + const id = category ? `${category}/${generator}` : generator ?? '' const modelConfig = config.models.find(m => m.id === id) if (!modelConfig) { - return
Not found
+ return
} const minVersion = config.models.find(m => m.id === id)?.minVersion ?? '1.15' @@ -36,7 +42,9 @@ export function Generator({ lang, changeTitle, version, onChangeVersion, categor const [model, setModel] = useState(null) useEffect(() => { setModel(null) - getModel(version, id).then(m => setModel(m)) + getModel(version, id) + .then(m => setModel(m)) + .catch(e => setError(e.message)) }, [version, category, generator]) const reset = () => { @@ -75,15 +83,17 @@ export function Generator({ lang, changeTitle, version, onChangeVersion, categor const registry = (modelConfig.category ? modelConfig.category + '/' : '') + modelConfig.schema useEffect(() => { if (!modelConfig.path) return - getCollections(version).then(collections => { - const terms = (presetFilter ?? '').trim().split(' ') - const presets = collections.get(registry) - .map(p => p.slice(10)) - .filter(p => terms.every(t => p.includes(t))) - if (presets) { - setPresetResults(presets) - } - }) + getCollections(version) + .then(collections => { + const terms = (presetFilter ?? '').trim().split(' ') + const presets = collections.get(registry) + .map(p => p.slice(10)) + .filter(p => terms.every(t => p.includes(t))) + if (presets) { + setPresetResults(presets) + } + }) + .catch(e => setError(e.message)) }, [version, category, generator, presetFilter]) const loadPreset = (id: string) => { @@ -154,7 +164,8 @@ export function Generator({ lang, changeTitle, version, onChangeVersion, categor - + {error && } +
- +
- +
} diff --git a/src/styles/global.css b/src/styles/global.css index 1248155c..5e21eb9e 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -12,8 +12,8 @@ --nav-hover: #b4b3b0; --nav-faded: #4d4c4c; --nav-faded-hover: #6e6e6e; - --selection: rgba(103, 134, 221, 0.6); - --errors-background: #f13000c5; + --selection: #6786dd99; + --errors-background: #62190f; --errors-text: #ffffffcc; } @@ -31,8 +31,8 @@ --nav-hover: #565d64; --nav-faded: #9fa2a7; --nav-faded-hover: #bcbfc3; - --selection: rgba(103, 134, 221, 0.6); - --errors-background: #f13000c5; + --selection: #6786dd99; + --errors-background: #f66653; --errors-text: #000000cc; } @@ -51,8 +51,8 @@ --nav-hover: #565d64; --nav-faded: #9fa2a7; --nav-faded-hover: #bcbfc3; - --selection: rgba(103, 134, 221, 0.6); - --errors-background: #f13000c5; + --selection: #6786dd99; + --errors-background: #f66653; --errors-text: #000000cc; } } @@ -434,42 +434,20 @@ main.has-preview { fill: var(--accent-blue); } -.errors { - position: fixed; - display: flex; - bottom: 17px; - right: 17px; - margin: 5px; - border-radius: 3px; - background-color: var(--errors-background); - color: var(--errors-text); - fill: var(--errors-text); -} - .error { - display: flex; - align-items: center; - padding: 7px; + padding: 5px 14px; + margin: 12px 16px; + color: var(--text-1); + background-color: var(--errors-background); + border-radius: 3px; } -.error span:not(:last-child) { - padding-right: 11px; +.error > * { + margin: 10px 0; } -.errors .toggle { - padding: 6px; - width: 36px; - height: 36px; - cursor: pointer; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -.errors svg { - width: 24px; - height: 24px; +.error a { + color: var(--text-1) } .home {