Skip to content
Merged
2 changes: 2 additions & 0 deletions frontend/src/locale/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,8 @@
"BULK_IMPORT_INSTRUCTIONS_NEED_HELP_DOCS": "Sieh dir die {wildbookDocsLink} an oder kontaktiere den Support",
"BULK_IMPORT_INSTRUCTIONS_WILDBOOK_DOCS": "Wildbook-Dokumentation",
"BULK_IMPORT_INSTRUCTIONS_CLOSE_BUTTON": "Schließen",
"BULKIMPORT_ERROR_REQUIRE_PREFIX": "Erforderliches Projekt-ID-Präfix fehlt",
"BULKIMPORT_ERROR_REQUIRE_NAME": "Erforderlicher Forschungsprojektname fehlt",
"PHOTOS_UPLOADED_TITLE": "hochgeladene Fotos: {count}",
"PHOTOS_UPLOADED": "Fotos hochgeladen",
"PHOTOS_FAILED": "fehlgeschlagene Fotos",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,8 @@
"BULK_IMPORT_INSTRUCTIONS_NEED_HELP_DOCS": "Check the {wildbookDocsLink} for troubleshooting or contact support",
"BULK_IMPORT_INSTRUCTIONS_WILDBOOK_DOCS": "Wildbook Docs",
"BULK_IMPORT_INSTRUCTIONS_CLOSE_BUTTON": "Close",
"BULKIMPORT_ERROR_REQUIRE_PREFIX": "missing required project ID prefix",
"BULKIMPORT_ERROR_REQUIRE_NAME": "missing required research project name",
"PHOTOS_UPLOADED_TITLE": "photos uploaded: {count}",
"PHOTOS_UPLOADED": "photos uploaded",
"PHOTOS_FAILED": "photos failed",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locale/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,8 @@
"BULK_IMPORT_INSTRUCTIONS_NEED_HELP_DOCS": "Consulta {wildbookDocsLink} para resolución de problemas o contacto con soporte",
"BULK_IMPORT_INSTRUCTIONS_WILDBOOK_DOCS": "Documentación de Wildbook",
"BULK_IMPORT_INSTRUCTIONS_CLOSE_BUTTON": "Cerrar",
"BULKIMPORT_ERROR_REQUIRE_PREFIX": "falta el prefijo de ID del proyecto obligatorio",
"BULKIMPORT_ERROR_REQUIRE_NAME": "falta el nombre del proyecto de investigación obligatorio",
"PHOTOS_UPLOADED_TITLE": "fotos subidas: {count}",
"PHOTOS_UPLOADED": "fotos subidas",
"PHOTOS_FAILED": "fotos fallidas",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locale/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,8 @@
"BULK_IMPORT_INSTRUCTIONS_NEED_HELP_DOCS": "Consultez {wildbookDocsLink} pour le dépannage ou contactez le support",
"BULK_IMPORT_INSTRUCTIONS_WILDBOOK_DOCS": "Docs Wildbook",
"BULK_IMPORT_INSTRUCTIONS_CLOSE_BUTTON": "Fermer",
"BULKIMPORT_ERROR_REQUIRE_PREFIX": "préfixe d’identifiant de projet requis manquant",
"BULKIMPORT_ERROR_REQUIRE_NAME": "nom du projet de recherche requis manquant",
"PHOTOS_UPLOADED_TITLE": "photos téléchargées : {count}",
"PHOTOS_UPLOADED": "photos téléchargées",
"PHOTOS_FAILED": "échecs photos",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locale/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,8 @@
"BULK_IMPORT_INSTRUCTIONS_NEED_HELP_DOCS": "Consulta {wildbookDocsLink} per risoluzione problemi o contatta il supporto",
"BULK_IMPORT_INSTRUCTIONS_WILDBOOK_DOCS": "Documentazione Wildbook",
"BULK_IMPORT_INSTRUCTIONS_CLOSE_BUTTON": "Chiudi",
"BULKIMPORT_ERROR_REQUIRE_PREFIX": "manca il prefisso ID progetto obbligatorio",
"BULKIMPORT_ERROR_REQUIRE_NAME": "manca il nome del progetto di ricerca obbligatorio",
"PHOTOS_UPLOADED_TITLE": "foto caricate: {count}",
"PHOTOS_UPLOADED": "foto caricate",
"PHOTOS_FAILED": "foto non riuscite",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const ErrorSummaryBar = observer(({ store }) => {

Object.values(errors).forEach((rowErrors) => {
Object.values(rowErrors).forEach((errMsg) => {
if (/required/i.test(JSON.stringify(errMsg))) {
if (/require/i.test(JSON.stringify(errMsg))) {
missingField += 1;
} else if (
/invalid/i.test(JSON.stringify(errMsg)) ||
Expand Down
71 changes: 71 additions & 0 deletions frontend/src/pages/BulkImport/BulkImportStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -1669,6 +1669,77 @@ export class BulkImportStore {
}
});
});

const prefixRe = /^Encounter\.project(\d+)\.projectIdPrefix$/;
const nameRe = /^Encounter\.project(\d+)\.researchProjectName$/;

const prefixIdx = new Set();
const nameIdx = new Set();

this._columnsDef.forEach((col) => {
let m = prefixRe.exec(col);
if (m) prefixIdx.add(m[1]);

m = nameRe.exec(col);
if (m) nameIdx.add(m[1]);
});

const allIdx = new Set([...prefixIdx, ...nameIdx]);

const ensureRowErrorMap = (rowIndex) => {
if (!errors[rowIndex]) errors[rowIndex] = {};
return errors[rowIndex];
};

allIdx.forEach((idx) => {
const hasPrefixCol = prefixIdx.has(idx);
const hasNameCol = nameIdx.has(idx);

if (hasPrefixCol === hasNameCol) return;

const prefixKey = `Encounter.project${idx}.projectIdPrefix`;
const nameKey = `Encounter.project${idx}.researchProjectName`;

const row0 = ensureRowErrorMap(0);

if (!hasPrefixCol && hasNameCol) {
row0[nameKey] = "BULKIMPORT_ERROR_REQUIRE_PREFIX";
}

if (hasPrefixCol && !hasNameCol) {
row0[prefixKey] = "BULKIMPORT_ERROR_REQUIRE_NAME";
}
});

this._spreadsheetData.forEach((row, rowIndex) => {
allIdx.forEach((idx) => {
if (!prefixIdx.has(idx) || !nameIdx.has(idx)) return;

const prefixKey = `Encounter.project${idx}.projectIdPrefix`;
const nameKey = `Encounter.project${idx}.researchProjectName`;

const norm = (v) => String(v ?? "").trim();

const prefixVal = norm(row[prefixKey]);
const nameVal = norm(row[nameKey]);

const hasPrefixVal = prefixVal !== "";
const hasNameVal = nameVal !== "";

if (hasPrefixVal !== hasNameVal) {
const rowErr = ensureRowErrorMap(rowIndex);

if (!hasPrefixVal && hasNameVal) {
rowErr[nameKey] = "BULKIMPORT_ERROR_REQUIRE_PREFIX";
}

if (hasPrefixVal && !hasNameVal) {
rowErr[prefixKey] = "BULKIMPORT_ERROR_REQUIRE_NAME";
}
}
});
});

this._cachedValidation = { errors, warnings };
return this._cachedValidation;
}
Expand Down
11 changes: 9 additions & 2 deletions frontend/src/pages/BulkImport/EditableDataTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@ const EditableCell = observer(
return store.getOptionsForSelectCell(columnId);
}, [columnId, store]);
const selectValue = useMemo(() => {
return value ? { value, label: value } : null;
if (
value === null ||
value === undefined ||
String(value).trim() === ""
) {
return null;
}
return { value, label: String(value) };
}, [value]);

const [showDetail, setShowDetail] = useState(false);
Expand Down Expand Up @@ -62,7 +69,7 @@ const EditableCell = observer(
<input
type="text"
className={`form-control form-control-sm rounded ${store.validationErrors?.[rowIndex]?.[columnId] ? "is-invalid" : ""}`}
value={store.spreadsheetData?.[rowIndex]?.[columnId] || ""}
value={store.spreadsheetData?.[rowIndex]?.[columnId] ?? ""}
title={value}
onKeyDown={(e) => {
if (e.key === "Enter") {
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/org/ecocean/api/bulk/BulkImportUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,29 @@ public static Map<String, Object> validateRow(JSONObject row, Shepherd myShepher
ApiException.ERROR_RETURN_CODE_INVALID));
}
}

// 1314 introduces catching incomplete project name/prefix combos
List<String> projectPrefixes = findIndexedFieldNames(fieldNames, "Encounter.project.projectIdPrefix");
List<String> projectNames = findIndexedFieldNames(fieldNames, "Encounter.project.researchProjectName");
// we use the bigger of these
int pmax = Integer.max(projectPrefixes.size(), projectNames.size());
for (int i = 0; i < pmax; i++) {
String pnameKey = "Encounter.project" + i + ".researchProjectName";
String pprefixKey = "Encounter.project" + i + ".projectIdPrefix";
Object pname = getValue(rtn, pnameKey);
Object pprefix = getValue(rtn, pprefixKey);
if ((pname == null) && (pprefix == null)) continue;
if ((pname != null) && (pprefix != null)) continue;
if (pname == null)
rtn.put(pnameKey,
new BulkValidatorException("must have researchProjectName if given projectIdPrefix",
ApiException.ERROR_RETURN_CODE_REQUIRED));
if (pprefix == null)
rtn.put(pprefixKey,
new BulkValidatorException("must have projectIdPrefix if given researchProjectName",
ApiException.ERROR_RETURN_CODE_REQUIRED));
}

return rtn;
}

Expand Down
Loading