This commit is contained in:
2025-10-17 14:39:34 +08:00
parent 28bbc3691b
commit 39cc4f4c2e
5 changed files with 580 additions and 306 deletions

255
main.js
View File

@@ -1,93 +1,192 @@
import { kintonePrettyFields } from './fields.js';
import { getGuestSpaceId, createFieldWithTooltips, createFieldLabels, getColumnWidths } from './dom.js';
import { getGuestSpaceId, createFieldWithLabels, createFieldLabels, getColumnWidths } from './dom.js';
import { KintoneRestAPIClient } from '@kintone/rest-api-client';
import { COLORS } from './constants.js';
export async function runKintoneHelper() {
const guestSpaceId = getGuestSpaceId();
/**
* Fetches form data from Kintone API
* @param {number} appId - The application ID
* @param {string} language - User language setting
* @returns {Promise<Object>} Form fields and layout data
*/
const fetchFormData = async (appId, language) => {
const client = new KintoneRestAPIClient({
guestSpaceId: guestSpaceId,
guestSpaceId: getGuestSpaceId(),
});
const appId = kintone.app.getId();
if (appId === null) return;
const language = kintone.getLoginUser().language;
const isPreview = false;
const { properties: formFields } = await client.app.getFormFields({
app: appId,
lang: language,
preview: isPreview,
});
const { layout: layout } = await client.app.getFormLayout({
app: appId,
preview: isPreview,
});
const { fields: fieldsWithLabels, spacers: spacerElements } =
kintonePrettyFields.generateFields(formFields, layout);
try {
const [formFieldsResult, layoutResult] = await Promise.all([
client.app.getFormFields({
app: appId,
lang: language,
preview: isPreview,
}),
client.app.getFormLayout({
app: appId,
preview: isPreview,
}),
]);
return {
formFields: formFieldsResult.properties,
layout: layoutResult.layout,
};
} catch (error) {
console.error('Failed to fetch form data:', error);
throw new Error('Could not retrieve form configuration');
}
};
/**
* Adds label to a subtable field element
* @param {Object} field - Field configuration
* @param {HTMLElement} fieldElement - The field DOM element
*/
const addSubtableLabel = (field, fieldElement) => {
// Add field code label above the table
fieldElement.before(
createFieldWithLabels({
code: field.code,
type: field.type,
})
);
// Add column labels below the table
const fieldNames = Object.keys(field.fields);
const columnWidths = getColumnWidths(fieldElement, field.type);
fieldElement.after(
createFieldLabels(fieldNames, columnWidths, field.type)
);
};
/**
* Adds label to a reference table field element
* @param {Object} field - Field configuration
* @param {HTMLElement} fieldElement - The field DOM element
*/
const addReferenceTableLabel = (field, fieldElement) => {
// Add field code label above the reference table
fieldElement.before(
createFieldWithLabels({
code: field.code,
type: field.type,
})
);
// Add display field labels if available
if (field.referenceTable?.displayFields) {
const displayFields = field.referenceTable.displayFields;
const columnWidths = getColumnWidths(fieldElement, field.type);
fieldElement.appendChild(
createFieldLabels(displayFields, columnWidths, field.type)
);
}
};
/**
* Adds label to a group field element
* @param {Object} field - Field configuration
* @param {HTMLElement} fieldElement - The field DOM element
*/
const addGroupLabel = (field, fieldElement) => {
fieldElement.parentElement?.before(
createFieldWithLabels({
code: field.code,
type: field.type,
})
);
};
/**
* Adds label to a standard field element
* @param {Object} field - Field configuration
* @param {HTMLElement} fieldElement - The field DOM element
*/
const addStandardFieldLabel = (field, fieldElement) => {
fieldElement.before(
createFieldWithLabels({
code: field.code,
type: field.type,
})
);
};
/**
* Processes and adds labels to all field elements on the page
* @param {Array} fieldsWithLabels - Processed field objects with label info
*/
const processFieldLabels = (fieldsWithLabels) => {
for (const field of fieldsWithLabels) {
const fieldElement = kintone.app.record.getFieldElement(field.code);
if (fieldElement) {
if (kintonePrettyFields.isSubtable(field)) {
fieldElement.before(
createFieldWithTooltips({
code: field.code,
type: field.type,
})
);
const fieldNames = Object.keys(field.fields);
const columnWidths = getColumnWidths(fieldElement, field.type);
fieldElement.after(
createFieldLabels(fieldNames, columnWidths, field.type)
);
continue;
}
if (!fieldElement) continue;
if (kintonePrettyFields.isReferenceTable(field)) {
fieldElement.before(
createFieldWithTooltips({
code: field.code,
type: field.type,
})
);
if (field.referenceTable) {
const displayFields = field.referenceTable.displayFields;
const columnWidths = getColumnWidths(fieldElement, field.type);
fieldElement.appendChild(
createFieldLabels(displayFields, columnWidths, field.type)
);
}
continue;
}
if (kintonePrettyFields.isGroup(field)) {
fieldElement.parentElement?.before(
createFieldWithTooltips({
code: field.code,
type: field.type,
}),
);
continue;
}
fieldElement.before(
createFieldWithTooltips({
code: field.code,
type: field.type,
}),
);
// Handle different field types with appropriate label placement
if (kintonePrettyFields.isSubtable(field)) {
addSubtableLabel(field, fieldElement);
} else if (kintonePrettyFields.isReferenceTable(field)) {
addReferenceTableLabel(field, fieldElement);
} else if (kintonePrettyFields.isGroup(field)) {
addGroupLabel(field, fieldElement);
} else {
addStandardFieldLabel(field, fieldElement);
}
}
};
/**
* Processes and adds labels to spacer elements on the page
* @param {Array} spacerElements - Spacer element configurations
*/
const processSpacerLabels = (spacerElements) => {
for (const spacer of spacerElements) {
const spacerElement = kintone.app.record.getSpaceElement(spacer.elementId);
if (spacerElement) {
spacerElement.appendChild(
createFieldWithTooltips({
code: spacer.elementId,
}),
);
spacerElement.style.border = "1px dotted blue";
}
}
}
if (!spacerElement) continue;
// Execute immediately upon injection
runKintoneHelper().catch(console.error);
// Add label and blue border to spacer elements
spacerElement.appendChild(
createFieldWithLabels({
code: spacer.elementId,
})
);
spacerElement.style.border = COLORS.SPACER_BORDER;
}
};
/**
* Main function to enhance Kintone forms with labels and visual helpers
* @returns {Promise<void>}
*/
export const runKintoneHelper = async () => {
try {
// Early return if not in a valid app context
const appId = kintone.app.getId();
if (!appId) {
console.log('Not in a valid Kintone app context');
return;
}
// Fetch necessary form configuration
const language = kintone.getLoginUser().language;
const { formFields, layout } = await fetchFormData(appId, language);
// Process fields and generate label data
const { fields: fieldsWithLabels, spacers: spacerElements } =
kintonePrettyFields.generateFields(formFields, layout);
// Apply labels to field elements
processFieldLabels(fieldsWithLabels);
// Apply visual indicators to spacer elements
processSpacerLabels(spacerElements);
console.log('Kintone helper labels applied successfully');
} catch (error) {
console.error('Failed to run Kintone helper:', error);
// Could implement user-friendly error notification here
}
};
// Execute helper function immediately when the script is injected
runKintoneHelper();