Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion meta_creator/templates/meta_creator/showdata.html
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ <h1>Extra Hints!</h1>
{% endfor %}
<!-- Add Row Inputs -->
<tr class="add-row-controls" data-table-key="{{ key }}">
<td></td>
<td class="disabled"></td>
{% for col, value in specific_types.items %}
{% if value == 'tagging' or value == 'tagging_autocomplete' %}
<td class="tags-table-container add-row-tags-container" data-type={{default_type}} data-coltype="{{ value }}" data-col="{{ col }}">
Expand Down
7 changes: 5 additions & 2 deletions static/foundation/css/foundation.css
Original file line number Diff line number Diff line change
Expand Up @@ -656,9 +656,12 @@ tr.add-row-controls td {
box-sizing: border-box;
padding: 0.5em;
vertical-align: middle;
background: #f9f9f9; /* Optional: subtle highlight */
background: #dddddd; /* Optional: subtle highlight */
}
.disabled {
cursor: not-allowed;
pointer-events: none;
}

/* For the table elements in the add-row-control row*/
tr.add-row-controls td {
/* Remove any display:block/flex if present */
Expand Down
232 changes: 125 additions & 107 deletions static/foundation/js/vendor/table-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,6 @@ export function setupTables() {

// If neither condition is satisfied → stop row creation
if (!condition1 && !condition2) {
// alert(
// "Please fill either: Identifier + Given Name + Family Name OR Given Name + Family Name + Email."
// );
showToast(
"Please fill either: Identifier + Given Name + Family Name OR Given Name + Family Name + Email.",
"error",
Expand All @@ -276,7 +273,6 @@ export function setupTables() {
(tr) =>
!tr.classList.contains("add-row-controls") && tr.querySelector("td"),
);
console.log(existingRows);

// Define which columns determine uniqueness
const columnsToCheck = ["identifier", "givenName", "familyName", "email"];
Expand Down Expand Up @@ -305,7 +301,6 @@ export function setupTables() {
const keysToCompare = Object.keys(newRowData).filter(
(k) => newRowData[k] !== "",
);
console.log(keysToCompare);
if (keysToCompare.length > 0) {
let isDuplicate = false;

Expand Down Expand Up @@ -345,6 +340,52 @@ export function setupTables() {
return; // Stop adding the new row
}
}
// Special validation for copyrightHolderTable
if (table.id === "copyrightHolderTable") {
const legalName = getInputVal("legalName");
const identifier = getInputVal("identifier");

const existingRows = Array.from(
table.querySelectorAll("tbody tr"),
).filter(
(tr) =>
!tr.classList.contains("add-row-controls") &&
tr.querySelector("td"),
);

const headers = Array.from(table.querySelectorAll("thead th")).map(
(th) => th.getAttribute("data-col"),
);

const legalNameIndex = headers.indexOf("legalName");
const identifierIndex = headers.indexOf("identifier");

// If identifier is empty → check duplicate legalName with empty identifier
if (!identifier) {
const duplicateExists = existingRows.some((row) => {
const cells = row.querySelectorAll("td");

const existingLegalName =
cells[legalNameIndex]?.textContent.trim().toLowerCase() || "";

const existingIdentifier =
cells[identifierIndex]?.textContent.trim().toLowerCase() || "";

return (
existingLegalName === legalName.toLowerCase() &&
!existingIdentifier
);
});

if (duplicateExists) {
showToast(
"Same Legal Name without Identifier already exists.",
"error",
);
return;
}
}
}

// Create new row
const newRow = document.createElement("tr");
Expand Down Expand Up @@ -554,25 +595,6 @@ export function setupTables() {
// functionanilties within all auto-property-tables
document.querySelectorAll("table.auto-property").forEach(function (table) {
table.addEventListener("click", function (e) {
// Delete rows
// if (e.target.classList.contains("delete-row-btn")) {
// const actionCell = e.target.closest(".action");
// console.log(actionCell);
// const confirmBox = actionCell.querySelector(".delete-row");
// confirmBox.style.display = "";
// const row = e.target.closest("tr");

// if (row) {
// row.remove();
// // Update the hidden input
// const tableId = table.id;
// if (tableId && tableId.endsWith("Table")) {
// const key = tableId.replace(/Table$/, "");
// updateTableHiddenInput(key);
// }
// }
// }

// Update other fields
// Only allow editing on <td> that is not the last column (delete icon)
const cell = e.target.closest("td");
Expand All @@ -598,7 +620,60 @@ export function setupTables() {

// Save on blur or Enter
function save() {
cell.textContent = input.value;
cell.textContent = input.value.trim();

// Only validate for copyright holder table
if (table.id === "copyrightHolderTable") {
const rows = table.querySelectorAll("tbody tr");

const legalName = row.children[0].textContent.trim();
const identifier = row.children[1].textContent.trim();

// Both fields empty
if (legalName === "" && identifier === "") {
showToast(
"Both Identifier and Legal Name can't be empty.",
Comment thread
Sundraiz-Shah marked this conversation as resolved.
Outdated
"error",
);
cell.textContent = oldValue;
return;
}

let duplicate = false;
let identifierDuplicate = false;

rows.forEach((r) => {
if (r === row) return;

const rLegalName = r.children[0].textContent.trim();
const rIdentifier = r.children[1].textContent.trim();

// Check identifier uniqueness
if (rIdentifier === identifier && identifier !== "") {
identifierDuplicate = true;
}

// Check combination duplicate
if (rLegalName === legalName && rIdentifier === identifier) {
duplicate = true;
}
});

if (identifierDuplicate) {
showToast("Identifier already exists.", "error");
cell.textContent = oldValue;
return;
}

if (duplicate) {
showToast(
"Same Legal Name and Identifier already exists.",
Comment thread
Sundraiz-Shah marked this conversation as resolved.
Outdated
"error",
);
cell.textContent = oldValue;
return;
}
}
// Update the hidden input for this table
const tableId = table.id;
if (tableId && tableId.endsWith("Table")) {
Expand Down Expand Up @@ -754,9 +829,11 @@ export function setupTables() {
const tags = emailCell.querySelectorAll(".tag");

if (tags.length > 0) {
emails = Array.from(tags).map((t) => t.dataset.tag);
emails = Array.from(tags).map((t) =>
(t.dataset.tag || "").trim().toLowerCase(),
);
} else if (emailCell.textContent.trim() !== "") {
emails = [emailCell.textContent.trim()];
emails = [emailCell.textContent.trim().toLowerCase()];
}
}

Expand Down Expand Up @@ -800,7 +877,14 @@ export function setupTables() {
Object.values(grouped).forEach((group) => {
if (group.length > 1) {
const mainRow = group[0].row;
const allEmails = [...new Set(group.flatMap((g) => g.emails))];
const allEmails = [
...new Set(
group
.flatMap((g) => g.emails)
.filter(Boolean)
.map((e) => e.trim().toLowerCase()),
),
];

// 🔸 Aggregate identifier + decide if we can merge
let mergedIdentifier = "";
Expand Down Expand Up @@ -1015,71 +1099,6 @@ export function initializeTableTaggingCells() {
}

const col = cell.getAttribute("data-col");
const colType = cell.getAttribute("data-coltype");
const dataType = cell.getAttribute("data-type");

// if (colType == "tagging_autocomplete") {
// // getSchema().then((schema) => {
// // autocompleteSource =
// // schema["$defs"]?.[dataType]?.properties?.[col]?.items?.enum || [];
// // if (autocompleteSource.length > 0) {
// // setupTableTagAutocomplete({ cell, autocompleteSource });
// // }
// // });
// } else
// if (colType === "dropdown") {
// const currentValue =
// cell.getAttribute("data-value") || cell.textContent.trim() || "";
// cell.innerHTML = "";
// cell.textContent = currentValue;

// // cell.addEventListener("click", function handleDropdownCellClick(e) {
// // if (cell.querySelector("select")) return;
// // getSchema().then((schema) => {
// // const options =
// // schema["$defs"]?.[dataType]?.properties?.[col]?.enum || [];
// // const select = document.createElement("select");
// // select.className = "table-dropdown-select";
// // select.name = "ChangingSelect";
// // select.innerHTML =
// // '<option value="">Select...</option>' +
// // options
// // .map((opt) => `<option value="${opt}">${opt}</option>`)
// // .join("");
// // select.value = currentValue;

// // cell.innerHTML = "";
// // cell.appendChild(select);
// // select.focus();

// // function finalizeSelection() {
// // const selectedValue = select.value;
// // cell.setAttribute("data-value", selectedValue);
// // setTimeout(() => {
// // cell.innerHTML = selectedValue;
// // }, 0);

// // cell.removeEventListener("click", handleDropdownCellClick);
// // setTimeout(() => {
// // cell.addEventListener("click", handleDropdownCellClick);
// // }, 0);

// // const table = cell.closest("table");
// // if (table && table.id.endsWith("Table")) {
// // const key = table.id.replace(/Table$/, "");
// // updateTableHiddenInput(key);
// // }
// // }

// // select.addEventListener("change", finalizeSelection);
// // select.addEventListener("blur", finalizeSelection);
// // });

// // cell.removeEventListener("click", handleDropdownCellClick);
// // });

// return;
// }

// Show input when cell is clicked
cell.addEventListener("click", function (e) {
Expand All @@ -1105,6 +1124,8 @@ export function initializeTableTaggingCells() {
e.preventDefault();
e.stopPropagation();
const tag = input.value.trim();
// Normalize email (case-insensitive)
const normalizedTag = tag.toLowerCase();

// ✅ Email Validation
if (col === "email") {
Expand All @@ -1115,6 +1136,17 @@ export function initializeTableTaggingCells() {
//input.value = "";
return; // ❌ Stop tag creation
}

// Check if email already exists
const alreadyExists = [...tagsList.querySelectorAll(".tag")].some(
(t) => (t.dataset.tag || "").toLowerCase() === normalizedTag,
);

if (alreadyExists) {
showToast("This email is already added.", "error");
Comment thread
Sundraiz-Shah marked this conversation as resolved.
Outdated
input.value = "";
return; // Stop tag creation
}
}

if (
Expand All @@ -1126,20 +1158,6 @@ export function initializeTableTaggingCells() {
return;
}

// let autocompleteSource = [];
// const colType = cell.getAttribute("data-coltype");
// if (colType === "tagging_autocomplete") {
// getSchema().then((schema) => {
// autocompleteSource =
// schema["$defs"]?.[dataType]?.properties?.[col]?.items?.enum || [];
// if (!autocompleteSource.includes(tag)) {
// alert("Please select a value from the list.");
// input.value = "";
// return;
// }
// });
// }

const span = document.createElement("span");
span.className = "tag";
span.setAttribute("data-tag", tag);
Expand Down
Loading