diff --git a/nx/blocks/form/form.js b/nx/blocks/form/form.js index b21b3fcc..8256f75e 100644 --- a/nx/blocks/form/form.js +++ b/nx/blocks/form/form.js @@ -8,6 +8,7 @@ import { getParentPointer } from './utils/pointer.js'; import { schemas as schemasPromise } from './utils/schema.js'; import { findNodeByPointer, + isDaDocumentResource, isEmptyDocumentHtml, isStructuredContentHtml, loadHtml, @@ -37,8 +38,7 @@ class FormEditor extends LitElement { details: { attribute: false }, formModel: { state: true }, _schemas: { state: true }, - _hasUnsupportedContent: { state: true }, - _missingSchemaName: { state: true }, + _formBlocker: { state: true }, _activeNavPointer: { state: true }, _scrollEditorIntoView: { state: true }, _scrollNavItemIntoView: { state: true }, @@ -48,8 +48,7 @@ class FormEditor extends LitElement { constructor() { super(); this._pendingSchemaId = ''; - this._hasUnsupportedContent = false; - this._missingSchemaName = undefined; + this._formBlocker = null; } connectedCallback() { @@ -60,8 +59,7 @@ class FormEditor extends LitElement { _resetEditorState() { this.formModel = null; - this._hasUnsupportedContent = false; - this._missingSchemaName = undefined; + this._formBlocker = null; this._pendingSchemaId = ''; this._activeNavPointer = undefined; this._scrollEditorIntoView = undefined; @@ -69,15 +67,37 @@ class FormEditor extends LitElement { } async fetchDoc() { + if (!isDaDocumentResource(this.details)) { + this._resetEditorState(); + this._formBlocker = { type: 'not-document' }; + return; + } + const resultPromise = loadHtml(this.details); const [schemas, result] = await Promise.all([schemasPromise, resultPromise]); if (schemas) this._schemas = schemas; - if (result.error || typeof result.html !== 'string') { + if (result.error) { + this._resetEditorState(); + const { status } = result; + if (status === 401 || status === 403) { + this._formBlocker = { type: 'no-access' }; + } else if (status === 404) { + // Folders and similar paths often yield 404 for the resolved source URL. + this._formBlocker = { type: 'not-document' }; + } else if (typeof status === 'number') { + this._formBlocker = { type: 'load-failed', status }; + } else { + this._formBlocker = { type: 'load-failed' }; + } + return; + } + + if (typeof result.html !== 'string') { this._resetEditorState(); - this._hasUnsupportedContent = true; + this._formBlocker = { type: 'load-failed' }; return; } @@ -88,13 +108,12 @@ class FormEditor extends LitElement { if (!isStructuredContentHtml(result.html)) { this._resetEditorState(); - this._hasUnsupportedContent = true; + this._formBlocker = { type: 'not-form-content' }; return; } const path = this.details.fullpath; - this._hasUnsupportedContent = false; - this._missingSchemaName = undefined; + this._formBlocker = null; this._activeNavPointer = undefined; this._scrollEditorIntoView = undefined; this._scrollNavItemIntoView = undefined; @@ -104,8 +123,7 @@ class FormEditor extends LitElement { if (!model.schema) { this._resetEditorState(); - this._hasUnsupportedContent = true; - this._missingSchemaName = schemaName ?? ''; + this._formBlocker = { type: 'missing-schema', schemaName: schemaName ?? '' }; return; } @@ -127,8 +145,7 @@ class FormEditor extends LitElement { const emptyForm = { data, metadata }; const path = this.details.fullpath; - this._hasUnsupportedContent = false; - this._missingSchemaName = undefined; + this._formBlocker = null; this._activeNavPointer = undefined; this._scrollEditorIntoView = undefined; this._scrollNavItemIntoView = undefined; @@ -152,6 +169,17 @@ class FormEditor extends LitElement { window.location.href = `https://da.live${query}#/${owner}/${repo}`; } + _getDisplayPath() { + const fullpath = (this.details?.fullpath ?? '').trim(); + return fullpath.toLowerCase().endsWith('.html') + ? fullpath.slice(0, -5) + : fullpath; + } + + _renderResourcePathSuffix(displayPath) { + return displayPath ? html` at ${displayPath}` : nothing; + } + _handleNavPointerSelectFromSidebar(e) { const { pointer } = e.detail ?? {}; if (!pointer || pointer === this._activeNavPointer) return; @@ -265,48 +293,73 @@ class FormEditor extends LitElement { } renderUnsupportedContentMessage() { - const fullpath = this.details?.fullpath ?? ''; - const path = fullpath.endsWith('.html') ? fullpath.slice(0, -5) : fullpath; const schemaEditorHref = this._getSchemaEditorHref(); - const hasMissingSchema = this._missingSchemaName !== undefined; - const schemaName = this._missingSchemaName || '(empty)'; + const blocker = this._formBlocker; const action = { label: 'Return to Home', style: '', click: () => this._goToRepoRoot(), }; + const displayPath = this._getDisplayPath(); + + let title = 'Unable to open'; + let body = html` +
+ This resource could not be opened. +
+ `; + + if (blocker?.type === 'missing-schema') { + const schemaName = blocker.schemaName || '(empty)'; + title = 'Schema not found'; + body = html` ++ No schema named ${schemaName}. + Schema Editor +
+ `; + } else if (blocker?.type === 'not-document' || blocker?.type === 'not-form-content') { + title = 'Unsupported resource'; + body = html` ++ This resource${this._renderResourcePathSuffix(displayPath)} is not Structured Content. +
+ `; + } else if (blocker?.type === 'no-access') { + title = 'Access denied'; + body = html` ++ You do not have access to this resource${this._renderResourcePathSuffix(displayPath)}. +
+ `; + } else if (blocker?.type === 'load-failed') { + title = 'Unable to load'; + body = html` ++ This resource could not be loaded. Try again later. +
+ `; + } + return html`- The schema ${schemaName} referenced by this resource - ${path ? html`at ${path} ` : ''}does not exist. To create it, open - Schema Editor. -
- ` - : html` -- The resource under this path${path ? html` ${path}` : ''} cannot be - opened as structured content. -
- `} + ${body}