Fix Monday.com push failures and improve error visibility
- Fix toast showing success when all cards fail (now shows error/warning) - Fix column value formatting: booleans use checkbox format, JSON arrays join as comma-separated strings, objects serialize properly - Filter out empty/null/undefined string values before sending to API - Add verbose logging to Monday.com GraphQL client for debugging Made-with: Cursor
This commit is contained in:
parent
034c73128f
commit
a0f5022de2
3 changed files with 48 additions and 5 deletions
|
|
@ -408,8 +408,13 @@ export default function SettingsPage() {
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
if (data.synced === 0 && data.failed === 0) {
|
if (data.synced === 0 && data.failed === 0) {
|
||||||
toast.success("All cards are already synced to Monday.com");
|
toast.success("All cards are already synced to Monday.com");
|
||||||
|
} else if (data.failed > 0 && data.synced === 0) {
|
||||||
|
const errDetail = data.errors?.[0] ? `\n${data.errors[0]}` : "";
|
||||||
|
toast.error(`All ${data.failed} card(s) failed to push to Monday.com${errDetail}`);
|
||||||
|
} else if (data.failed > 0) {
|
||||||
|
toast.warning(`Pushed ${data.synced} card(s), but ${data.failed} failed`);
|
||||||
} else {
|
} else {
|
||||||
toast.success(`Pushed ${data.synced} card(s) to Monday.com${data.failed > 0 ? ` (${data.failed} failed)` : ""}`);
|
toast.success(`Pushed ${data.synced} card(s) to Monday.com`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
toast.error(data.error || "Sync failed");
|
toast.error(data.error || "Sync failed");
|
||||||
|
|
|
||||||
|
|
@ -203,6 +203,8 @@ export async function pushCardToMonday(
|
||||||
const columnValues = mapCardToColumnValues(cardData, columnMap);
|
const columnValues = mapCardToColumnValues(cardData, columnMap);
|
||||||
const itemName = (card.name as string) || "Unnamed Card";
|
const itemName = (card.name as string) || "Unnamed Card";
|
||||||
|
|
||||||
|
console.log(`[pushCardToMonday] Card "${itemName}" (${cardId}), columnValues:`, JSON.stringify(columnValues));
|
||||||
|
|
||||||
if (card.mondayItemId) {
|
if (card.mondayItemId) {
|
||||||
await updateItem(token, boardId, card.mondayItemId, columnValues);
|
await updateItem(token, boardId, card.mondayItemId, columnValues);
|
||||||
return { action: "updated" as const, mondayItemId: card.mondayItemId };
|
return { action: "updated" as const, mondayItemId: card.mondayItemId };
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ const MONDAY_FILE_API = "https://api.monday.com/v2/file";
|
||||||
type MondayColumn = { id: string; title: string; type: string };
|
type MondayColumn = { id: string; title: string; type: string };
|
||||||
|
|
||||||
async function gql(token: string, query: string, variables?: Record<string, unknown>) {
|
async function gql(token: string, query: string, variables?: Record<string, unknown>) {
|
||||||
|
const body = JSON.stringify({ query, variables });
|
||||||
|
console.log("[monday gql] request:", body.slice(0, 500));
|
||||||
|
|
||||||
const res = await fetch(MONDAY_API, {
|
const res = await fetch(MONDAY_API, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -11,7 +14,7 @@ async function gql(token: string, query: string, variables?: Record<string, unkn
|
||||||
Authorization: token,
|
Authorization: token,
|
||||||
"API-Version": "2024-10",
|
"API-Version": "2024-10",
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ query, variables }),
|
body,
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const text = await res.text().catch(() => "");
|
const text = await res.text().catch(() => "");
|
||||||
|
|
@ -21,10 +24,12 @@ async function gql(token: string, query: string, variables?: Record<string, unkn
|
||||||
if (json.errors?.length) {
|
if (json.errors?.length) {
|
||||||
const err = json.errors[0];
|
const err = json.errors[0];
|
||||||
const detail = err.extensions ? ` (${JSON.stringify(err.extensions)})` : "";
|
const detail = err.extensions ? ` (${JSON.stringify(err.extensions)})` : "";
|
||||||
|
console.error("[monday gql] GraphQL error:", JSON.stringify(json.errors));
|
||||||
throw new Error(`Monday.com GraphQL: ${err.message}${detail}`);
|
throw new Error(`Monday.com GraphQL: ${err.message}${detail}`);
|
||||||
}
|
}
|
||||||
if (json.error_message) {
|
if (json.error_message) {
|
||||||
throw new Error(`Monday.com: ${json.error_message}`);
|
console.error("[monday gql] API error:", json.error_message, json.error_code);
|
||||||
|
throw new Error(`Monday.com: ${json.error_message} (${json.error_code || "unknown"})`);
|
||||||
}
|
}
|
||||||
return json.data;
|
return json.data;
|
||||||
}
|
}
|
||||||
|
|
@ -135,6 +140,33 @@ export async function readItem(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BOOLEAN_CARD_FIELDS = new Set([
|
||||||
|
"iSaidYesBookSent",
|
||||||
|
"ftGuestLetterSent",
|
||||||
|
"prayerForTeam",
|
||||||
|
"prayerConfidential",
|
||||||
|
]);
|
||||||
|
|
||||||
|
function formatValue(cardField: string, val: unknown): unknown | null {
|
||||||
|
if (BOOLEAN_CARD_FIELDS.has(cardField) || typeof val === "boolean") {
|
||||||
|
return { checked: val === true || val === "true" ? "true" : "false" };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
const joined = val.filter(Boolean).join(", ");
|
||||||
|
return joined || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof val === "object") {
|
||||||
|
const s = JSON.stringify(val);
|
||||||
|
return s === "{}" || s === "[]" ? null : s;
|
||||||
|
}
|
||||||
|
|
||||||
|
const strVal = String(val).trim();
|
||||||
|
if (strVal === "" || strVal === "null" || strVal === "undefined" || strVal === "[object Object]") return null;
|
||||||
|
return strVal;
|
||||||
|
}
|
||||||
|
|
||||||
export function mapCardToColumnValues(
|
export function mapCardToColumnValues(
|
||||||
card: Record<string, unknown>,
|
card: Record<string, unknown>,
|
||||||
columnMap: Record<string, string>
|
columnMap: Record<string, string>
|
||||||
|
|
@ -142,10 +174,14 @@ export function mapCardToColumnValues(
|
||||||
const values: Record<string, unknown> = {};
|
const values: Record<string, unknown> = {};
|
||||||
|
|
||||||
for (const [cardField, colId] of Object.entries(columnMap)) {
|
for (const [cardField, colId] of Object.entries(columnMap)) {
|
||||||
if (!colId || !cardField) continue;
|
if (!colId || !cardField || cardField.startsWith("_")) continue;
|
||||||
const val = card[cardField];
|
const val = card[cardField];
|
||||||
if (val === null || val === undefined) continue;
|
if (val === null || val === undefined) continue;
|
||||||
values[colId] = String(val);
|
|
||||||
|
const formatted = formatValue(cardField, val);
|
||||||
|
if (formatted !== null) {
|
||||||
|
values[colId] = formatted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return values;
|
return values;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue