Show BIM comment API failures
This commit is contained in:
parent
2b89977083
commit
2aab1bc9b4
|
|
@ -2197,6 +2197,12 @@ header {
|
|||
border-top: 1px solid rgba(255, 255, 255, 0.04);
|
||||
}
|
||||
|
||||
.comment-card-modal__footer-error {
|
||||
grid-column: 1 / -1;
|
||||
min-height: 0;
|
||||
padding: 0 2px 2px;
|
||||
}
|
||||
|
||||
.comment-card-modal__footer .primary-btn,
|
||||
.comment-card-modal__footer .secondary-btn {
|
||||
min-width: 0;
|
||||
|
|
|
|||
|
|
@ -544,6 +544,13 @@ const formatDateTime = (value) => {
|
|||
}
|
||||
};
|
||||
|
||||
const setCommentModalError = (message = "") => {
|
||||
if (!commentModalError) return;
|
||||
const text = String(message || "").trim();
|
||||
commentModalError.textContent = text;
|
||||
commentModalError.hidden = !text;
|
||||
};
|
||||
|
||||
const bringFloatingWindowToFront = (id) => {
|
||||
if (!id) return;
|
||||
floatingWindowOrder = [...floatingWindowOrder.filter((item) => item !== id), id];
|
||||
|
|
@ -938,8 +945,8 @@ const readAttachmentFiles = async (fileList) => {
|
|||
.filter((file) => file && file.size <= COMMENT_FILE_LIMIT_BYTES)
|
||||
.slice(0, 8);
|
||||
const skipped = Array.from(fileList || []).filter((file) => file && file.size > COMMENT_FILE_LIMIT_BYTES).length;
|
||||
if (skipped && commentModalError) {
|
||||
commentModalError.textContent = `Файлы больше 50 МБ не добавлены: ${skipped}`;
|
||||
if (skipped) {
|
||||
setCommentModalError(`Файлы больше 50 МБ не добавлены: ${skipped}`);
|
||||
}
|
||||
const readOne = (file) => new Promise((resolve) => {
|
||||
const reader = new FileReader();
|
||||
|
|
@ -1215,7 +1222,7 @@ const openCommentModalForTarget = () => {
|
|||
? `Последнее редактирование: новая точка ${x.toFixed(2)}, ${y.toFixed(2)}, ${z.toFixed(2)}`
|
||||
: "Последнее редактирование: новый комментарий";
|
||||
}
|
||||
if (commentModalError) commentModalError.textContent = "";
|
||||
setCommentModalError("");
|
||||
resetCommentModalAttachments();
|
||||
renderCommentThread(null);
|
||||
commentModalBackdrop?.classList.remove("hidden");
|
||||
|
|
@ -1242,7 +1249,7 @@ const openCommentModalForComment = (commentId) => {
|
|||
if (commentModalEditedMeta) {
|
||||
commentModalEditedMeta.textContent = `Последнее редактирование: ${formatDateTime(comment.updatedAt || comment.createdAt)}`;
|
||||
}
|
||||
if (commentModalError) commentModalError.textContent = "";
|
||||
setCommentModalError("");
|
||||
resetCommentModalAttachments();
|
||||
commentDraftSubitems = Array.isArray(comment.subitems)
|
||||
? comment.subitems.map((item) => ({ ...item }))
|
||||
|
|
@ -1266,7 +1273,7 @@ const closeCommentModal = () => {
|
|||
activeCommentId = null;
|
||||
commentModalMode = "create";
|
||||
commentModalCommentId = null;
|
||||
if (commentModalError) commentModalError.textContent = "";
|
||||
setCommentModalError("");
|
||||
renderCommentsPanel();
|
||||
renderCommentTargets();
|
||||
};
|
||||
|
|
@ -1329,9 +1336,9 @@ const applyCommentModal = async ({ closeOnSave = false } = {}) => {
|
|||
const title = commentTitleInput?.value?.trim() || "";
|
||||
const body = commentBodyInput?.value?.trim() || "";
|
||||
const replyBody = commentReplyInput?.value?.trim() || "";
|
||||
if (commentModalError) commentModalError.textContent = "";
|
||||
setCommentModalError("");
|
||||
if (commentModalMode === "create" && !commentContextTarget?.worldPos) {
|
||||
if (commentModalError) commentModalError.textContent = "Не выбрана точка комментария";
|
||||
setCommentModalError("Не выбрана точка комментария");
|
||||
return;
|
||||
}
|
||||
commentSaveInFlight = true;
|
||||
|
|
@ -1399,7 +1406,7 @@ const applyCommentModal = async ({ closeOnSave = false } = {}) => {
|
|||
} catch (err) {
|
||||
console.error(err);
|
||||
const message = err.message || "Не удалось сохранить комментарий";
|
||||
if (commentModalError) commentModalError.textContent = message;
|
||||
setCommentModalError(message);
|
||||
setStatus(message);
|
||||
} finally {
|
||||
commentSaveInFlight = false;
|
||||
|
|
@ -3627,8 +3634,38 @@ const guessTypeFromName = (name) => {
|
|||
return null;
|
||||
};
|
||||
|
||||
const isApiRequestUrl = (url) => {
|
||||
try {
|
||||
return new URL(url, window.location.href).pathname.startsWith("/api/");
|
||||
} catch (_) {
|
||||
return String(url || "").startsWith("/api/");
|
||||
}
|
||||
};
|
||||
|
||||
const formatFetchFailureMessage = (url, res, text, data) => {
|
||||
const apiRequest = isApiRequestUrl(url);
|
||||
if (apiRequest && res.status === 401) {
|
||||
return "BIM API не принял запрос: нужна авторизация.";
|
||||
}
|
||||
if (apiRequest && res.status === 404) {
|
||||
return "BIM API недоступен на этом адресе. Открой viewer через node server/index.js, не через статический http-server.";
|
||||
}
|
||||
if (apiRequest && /^\s*<!doctype html/i.test(text || "")) {
|
||||
return `BIM API вернул HTML вместо JSON (HTTP ${res.status}). Проверь, что открыт backend-сервер BIM Viewer.`;
|
||||
}
|
||||
return (data && (data.message || data.error)) || text || `HTTP ${res.status}`;
|
||||
};
|
||||
|
||||
const fetchJSON = async (url, options = {}) => {
|
||||
const res = await fetch(url, options);
|
||||
let res = null;
|
||||
try {
|
||||
res = await fetch(url, options);
|
||||
} catch (err) {
|
||||
if (isApiRequestUrl(url)) {
|
||||
throw new Error(`BIM API недоступен: ${err?.message || "network error"}`);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
const text = await res.text();
|
||||
let data = null;
|
||||
try {
|
||||
|
|
@ -3637,7 +3674,7 @@ const fetchJSON = async (url, options = {}) => {
|
|||
// ignore parse errors, text will be used for message
|
||||
}
|
||||
if (!res.ok) {
|
||||
const message = (data && data.message) || text || `HTTP ${res.status}`;
|
||||
const message = formatFetchFailureMessage(url, res, text, data);
|
||||
throw new Error(message);
|
||||
}
|
||||
return data;
|
||||
|
|
|
|||
|
|
@ -413,9 +413,9 @@
|
|||
<div class="comment-attachment-grid comment-attachment-grid--reply" id="commentReplyAttachmentGrid"></div>
|
||||
<div class="comment-thread__list" id="commentThreadList"></div>
|
||||
</section>
|
||||
<div class="error-text" id="commentModalError"></div>
|
||||
</div>
|
||||
<div class="comment-card-modal__footer">
|
||||
<div class="error-text comment-card-modal__footer-error" id="commentModalError" hidden></div>
|
||||
<button class="secondary-btn" id="commentCancelButton" type="button">Отменить</button>
|
||||
<button class="primary-btn" id="commentApplyButton" type="button">Применить</button>
|
||||
<button class="primary-btn" id="commentSaveButton" type="button">Сохранить</button>
|
||||
|
|
@ -570,6 +570,6 @@
|
|||
<input id="fileInput" class="hidden" type="file"
|
||||
accept=".xkt,.glb,.gltf,.bim,.las,.laz,.obj,.stl">
|
||||
|
||||
<script type="module" src="./dcViewer.js?v=35"></script>
|
||||
<script type="module" src="./dcViewer.js?v=36"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Reference in New Issue