Skip to content

Commit 3cb3ecb

Browse files
committed
rework addRowsToBottom()
1 parent 5a36cea commit 3cb3ecb

File tree

2 files changed

+67
-98
lines changed

2 files changed

+67
-98
lines changed

lib/DataHarmonizer.js

+61-94
Original file line numberDiff line numberDiff line change
@@ -793,66 +793,78 @@ class DataHarmonizer {
793793

794794
/* Currently only called via Footer.js
795795
* numRows is (usually) user specified number of rows to add at bottom
796-
* of current dh table. However, if table has foreign key to another
797-
* table, the other table's focused row controls foreign key entries
796+
* of current dh table. However, if table has foreign key(s) to another
797+
* table, the other table's focused row will control foreign key values
798798
* added to this table.
799799
*/
800800
addRowsToBottom(numRows) {
801+
802+
numRows = parseInt(numRows); // Coming from form string input.
801803
// Get the starting row index where the new rows will be added
802804
const startRowIndex = this.hot.countRows();
803-
804-
if (! this.context.oneToManyAppContext) {
805+
806+
// If this has no foreign key parent table(s) then go ahead and add x rows.
807+
if (! this.context.relations?.[this.template_name]?.parent) {
805808
// Insert the new rows below the last existing row
806809
this.hot.alter('insert_row_below', startRowIndex, numRows);
807810
return;
808811
}
809812

810-
// Validate and process the current selection
811-
const is1mAndHasParent = (class_assignment) => {
812-
const unique_keys =
813-
this.context.oneToManyAppContext.appContext[class_assignment]
814-
.unique_keys;
815-
for (let key in unique_keys) {
816-
if ('foreign_key' in unique_keys[key]) {
817-
return unique_keys[key].foreign_key;
818-
}
813+
// Here we deal with adding rows that need foreign keys.
814+
// Locate each foreign key and fetch its focused value, and copy into new
815+
// records below.
816+
// If missing key value(s), prompt user to focus appropriate tab(s) row
817+
// and try again.
818+
819+
let required_selections = {};
820+
let selection_error = '';
821+
Object.entries(this.context.relations?.[this.template_name]?.parent)
822+
.forEach(([parent_name, parent]) => {
823+
Object.entries(parent)
824+
.forEach(([slot_name, foreign_slot_name]) => {
825+
// Determine if foreign key field has been selected
826+
let hot_parent = this.context.dhs[parent_name].hot;
827+
let slot_value;
828+
// getSelected() returns array with each row being a selection range
829+
// e.g. [[startRow, startCol, endRow, endCol],...].
830+
let selected = hot_parent.getSelected();
831+
if (selected) {
832+
let hot_col = this.getColumnIndexByFieldName(slot_name);
833+
// Get first selection's first row.
834+
slot_value = hot_parent.getDataAtCell(selected[0][0], hot_col);
835+
if (!slot_value || slot_value.length == 0) {
836+
selected = false;
837+
}
819838
}
820-
return false;
821-
};
822-
const classIsForeignKeyForClassAndCurrentSelection = (
823-
maybe_child_class,
824-
currentSelection
825-
) => {
826-
const unique_keys =
827-
this.context.oneToManyAppContext.appContext[maybe_child_class]
828-
.unique_keys;
829-
return (
830-
!isEmptyUnitVal(unique_keys[currentSelection.shared_key_name]) &&
831-
maybe_child_class !== currentSelection.source
832-
);
833-
};
834-
// check if the DH refers to a parent class or class with no children.
835-
// if it has a parent, ensure a foreign key is selected in some parent
836-
// if it doesn't have a parent, use regular add rows implementation
837-
if (is1mAndHasParent(this.class_assignment)) {
838-
if (
839-
!isEmptyUnitVal(this.context.currentSelection) &&
840-
!isEmptyUnitVal(this.context.currentSelection.valueToMatch) &&
841-
classIsForeignKeyForClassAndCurrentSelection(
842-
this.class_assignment,
843-
this.context.currentSelection
844-
)
845-
) {
846-
// Insert the new rows below the last existing row
847-
this.hot.alter('insert_row_below', startRowIndex, numRows);
848-
// Find the nearest index after the last non-empty row in the specified column
849-
this.populateNewRows(numRows, startRowIndex);
850-
} else {
851-
console.warn('No current selection to populate the new rows.');
852-
$('#empty-parent-key-modal').modal('show');
853-
}
839+
if (!selected) {
840+
//required_selections[slot_name] = {source: parent_name};
841+
selection_error += `<li> <b>${parent_name}</b> (${foreign_slot_name})</li>`;
842+
}
843+
else {
844+
required_selections[slot_name] = slot_value;
845+
}
846+
});
847+
});
848+
849+
if (selection_error) {
850+
// Prompt user to select appropriate parent table row(s) first.
851+
$('#empty-parent-key-modal-info').html(selection_error);
852+
$('#empty-parent-key-modal').modal('show');
853+
return;
854854
}
855855

856+
this.hot.alter('insert_row_below', startRowIndex, numRows);
857+
858+
// Populate new rows with selected value(s)
859+
this.hot.batch(() => {
860+
for (let row = startRowIndex; row < startRowIndex + numRows; row++) {
861+
Object.entries(required_selections).forEach(([slot_name, value]) => {
862+
const col = this.getColumnIndexByFieldName(slot_name);
863+
this.hot.setDataAtCell(row, col, value);
864+
});
865+
};
866+
});
867+
856868
}
857869

858870
getColumnIndexByFieldName(slot_name) {
@@ -865,53 +877,7 @@ class DataHarmonizer {
865877
return -1;
866878
}
867879

868-
// Function to populate the new rows with the selected value
869-
populateNewRows(numRows, baseColCoord) {
870-
const { shared_key_name, valueToMatch, source } =
871-
this.context.currentSelection;
872-
const col = this.getColumnIndexByFieldName(shared_key_name);
873-
874-
// Retrieve shared keys for the current class assignment, if any
875-
const sharedKeys =
876-
this.context.schema_tree[this.class_assignment]?.shared_keys || [];
877-
878-
if (valueToMatch !== null && sharedKeys.length > 0 && col !== -1) {
879-
sharedKeys.forEach((shared_key_spec) => {
880-
const { name, relation, related_concept } = shared_key_spec;
881-
882-
// Check if the current column matches the shared key and the source matches the related concept
883-
const currentColumnName = this.slots[col].name;
884-
const isMatchingKey =
885-
currentColumnName === name &&
886-
relation === 'parent' &&
887-
source === related_concept;
888-
889-
if (isMatchingKey) {
890-
this.hot.batch(() => {
891-
this.populateCells(numRows, baseColCoord, col, valueToMatch);
892-
});
893-
}
894-
});
895-
}
896-
}
897-
898-
// Function to populate cells with the selected value, checking for non-empty cells to avoid overwriting
899-
populateCells(numRows, baseColCoord, col, valueToMatch) {
900-
for (let i = 0; i < numRows; i++) {
901-
const targetRowIndex = baseColCoord + i;
902-
903-
// Check if the target row is empty before setting the value to avoid overwriting
904-
const existingValue = this.hot.getDataAtCell(targetRowIndex, col);
905-
if (existingValue === null || existingValue === '') {
906-
this.hot.setDataAtCell(targetRowIndex, col, valueToMatch);
907-
} else {
908-
console.warn(
909-
`Skipping row index ${targetRowIndex} as it already contains a value.`
910-
);
911-
}
912-
}
913-
}
914-
880+
/*
915881
// Function to find the nearest index after the last non-empty value
916882
findNearestIndexAfterLastNonEmpty(column) {
917883
// Initialize nearestIndex to the first index (0)
@@ -933,6 +899,7 @@ class DataHarmonizer {
933899
// Return the index immediately after the last non-empty value
934900
return nearestIndex;
935901
}
902+
*/
936903

937904
/**
938905
* Hides the columns at the specified indexes within the Handsontable instance.

lib/toolbar.html

+6-4
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@
232232
</div>
233233
</div>
234234

235-
<div class="btn-group" role="group" style="margin-right: 40px; display:none">
235+
<div class="btn-group" role="group" style="margin-right: 40px"> <!-- ; display:none-->
236236
<div class="input-group-prepend">
237237
<div class="btn" id="translation_label" data-i18n="translation_label">
238238
Language
@@ -1031,11 +1031,13 @@ <h5 id="template-help-title" data-i18n="template-help-title">
10311031
<div class="modal-body">
10321032
<div class="container-fluid">
10331033
<div class="row">
1034-
<div class="col text-danger">
1035-
Please select a parent row with a valid primary key before
1036-
adding child rows.
1034+
<div class="col text-danger" ><!--data-i18n="template-cancel"-->
1035+
Before new records can be inserted here, you need to select a parent table (tab) record so that it is linked by the appropriate key field value(s) below.
10371036
</div>
10381037
</div>
1038+
<div class="row">
1039+
<div class="col"><ul id="empty-parent-key-modal-info"></ul></div>
1040+
</div>
10391041
<div class="row mt-3">
10401042
<div class="col d-flex justify-content-end">
10411043
<button

0 commit comments

Comments
 (0)