Skip to content

Commit

Permalink
Merge pull request #370 from fairdataihub/staging
Browse files Browse the repository at this point in the history
feat: 15.2.3 bug fix release
  • Loading branch information
aaronm-2112 authored Nov 20, 2024
2 parents 1d71189 + 323e483 commit 79642c6
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 274 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to SODA will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## v15.2.3 - 2024-11-20

## Bug Fixes:

- Restricted forbidden characters in Guided Mode datasets to avoid JSON save file issues.
- Moved guidedSaveProgress to trigger after every successful page exit for broader save coverage.

## v15.2.2 - 2024-10-09

## Bug Fixes:
Expand Down
400 changes: 162 additions & 238 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "soda-for-sparc",
"procductName": "SODA for SPARC",
"version": "15.2.2",
"version": "15.2.3",
"description": "Keep Calm and Curate",
"main": "./out/main/index.js",
"author": "SODA Team",
Expand Down
2 changes: 1 addition & 1 deletion src/pyflask/startup/minimumApiVersion.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def get_api_version():
"""


return {'version': os.getenv('API_VERSION', "15.2.2")}
return {'version': os.getenv('API_VERSION', "15.2.3")}



79 changes: 48 additions & 31 deletions src/renderer/src/scripts/guided-mode/guided-curate-dataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -1095,11 +1095,15 @@ const savePageChanges = async (pageBeingLeftID) => {
message: "Please enter a dataset name.",
});
}
if (check_forbidden_characters_ps(datasetNameInput)) {

const datasetNameContainsForbiddenCharacters = window.evaluateStringAgainstSdsRequirements(
datasetNameInput,
"string-contains-forbidden-characters"
);
if (datasetNameContainsForbiddenCharacters) {
errorArray.push({
type: "notyf",
message:
"A Pennsieve dataset name cannot contain any of the following characters: /:*?'<>.",
message: `A Pennsieve dataset name cannot contain any of the following characters: @#$%^&*()+=/\|"'~;:<>{}[]?`,
});
}
if (!datasetSubtitleInput) {
Expand Down Expand Up @@ -2101,12 +2105,14 @@ const savePageChanges = async (pageBeingLeftID) => {
}
}

// Save the current version of SODA as the user should be taken back to the first page when the app is updated
const currentAppVersion = document.getElementById("version").innerHTML;
window.sodaJSONObj["last-version-of-soda-used"] = currentAppVersion;

// Stop any animations that need to be stopped
startOrStopAnimationsInContainer(pageBeingLeftID, "stop");

try {
await guidedSaveProgress();
} catch (error) {
log.error(error);
}
} catch (error) {
guidedSetNavLoadingState(false);
console.log(error);
Expand Down Expand Up @@ -3000,9 +3006,14 @@ const guidedTransitionFromDatasetNameSubtitlePage = () => {
$("#guided-footer-div").css("display", "flex");
};

const saveGuidedProgress = async (guidedProgressFileName) => {
const guidedSaveProgress = async () => {
const guidedProgressFileName = window.sodaJSONObj?.["digital-metadata"]?.["name"];
//return if guidedProgressFileName is not a strnig greater than 0
if (typeof guidedProgressFileName !== "string" || guidedProgressFileName.length === 0) {
if (
!guidedProgressFileName ||
typeof guidedProgressFileName !== "string" ||
guidedProgressFileName.length === 0
) {
return;
}
//Destination: HOMEDIR/SODA/Guided-Progress
Expand All @@ -3026,6 +3037,10 @@ const saveGuidedProgress = async (guidedProgressFileName) => {
window.sodaJSONObj["subjects-table-data"] = window.subjectsTableData;
window.sodaJSONObj["samples-table-data"] = window.samplesTableData;

// Save the current version of SODA as the user should be taken back to the first page when the app is updated
const currentAppVersion = document.getElementById("version").innerHTML;
window.sodaJSONObj["last-version-of-soda-used"] = currentAppVersion;

window.fs.writeFileSync(guidedFilePath, JSON.stringify(window.sodaJSONObj, null, 2));
};

Expand Down Expand Up @@ -3466,7 +3481,7 @@ window.guidedOpenManifestEditSwal = async (highLevelFolderName) => {
//spreadsheet reply contained results
await updateManifestJson(highLevelFolderName, result);
window.electron.ipcRenderer.removeAllListeners("spreadsheet-reply");
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();
renderManifestCards();
}
});
Expand Down Expand Up @@ -6815,7 +6830,7 @@ window.openPage = async (targetPageID) => {

// Set the last opened page and save it
window.sodaJSONObj["page-before-exit"] = targetPageID;
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();
} catch (error) {
const eMessage = userErrorMessage(error);
Swal.fire({
Expand Down Expand Up @@ -7537,7 +7552,7 @@ const guidedCheckIfUserNeedsToReconfirmAccountDetails = () => {
return false;
};

const guidedGetPageToReturnTo = (sodaJSONObj) => {
const guidedGetPageToReturnTo = async (sodaJSONObj) => {
// Set by window.openPage function
const usersPageBeforeExit = window.sodaJSONObj["page-before-exit"];

Expand All @@ -7553,7 +7568,11 @@ const guidedGetPageToReturnTo = (sodaJSONObj) => {
const lastVersionOfSodaUsedOnProgressFile = window.sodaJSONObj["last-version-of-soda-used"];

if (lastVersionOfSodaUsedOnProgressFile != currentSodaVersion) {
// If the last time the user worked on the progress file was in a previous version of SODA, then force the user to restart from the first page
// If the progress file was last edited in a previous SODA version, reset to the first page
await swalShowInfo(
"SODA has been updated since you last worked on this dataset.",
"You'll be taken to the first page to ensure compatibility with the latest workflow. Your previous work is saved and accessible."
);
return firstPageID;
}

Expand Down Expand Up @@ -7876,7 +7895,7 @@ window.guidedResumeProgress = async (datasetNameToResume) => {
hideSubNavAndShowMainNav(false);

// pageToReturnTo will be set to the page the user will return to
const pageToReturnTo = guidedGetPageToReturnTo(window.sodaJSONObj);
const pageToReturnTo = await guidedGetPageToReturnTo(window.sodaJSONObj);

await window.openPage(pageToReturnTo);

Expand Down Expand Up @@ -10546,7 +10565,7 @@ window.openCopySubjectMetadataPopup = async () => {
window.populateForms(currentSubjectOpenInView, "", "guided");
}

await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();
}
});
};
Expand Down Expand Up @@ -10644,7 +10663,7 @@ window.openCopySampleMetadataPopup = async () => {
if (currentSampleOpenInView) {
openModifySampleMetadataPage(currentSampleOpenInView, currentSampleSubjectOpenInView);
}
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();
}
});
};
Expand Down Expand Up @@ -12866,7 +12885,7 @@ const renderSubjectsMetadataAsideItems = async () => {
//check to see if previousSubject is empty
if (previousSubject) {
window.addSubject("guided");
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();
}

window.clearAllSubjectFormFields(window.guidedSubjectsFormDiv);
Expand All @@ -12884,7 +12903,7 @@ const renderSubjectsMetadataAsideItems = async () => {

document.getElementById("guided-bootbox-subject-id").value = e.target.innerText;

await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();
});
});
};
Expand Down Expand Up @@ -13011,7 +13030,7 @@ const renderSamplesMetadataAsideItems = async () => {
//check to see if previousSample is empty
if (previousSample) {
window.addSample("guided");
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();
}

//add selected class to clicked element
Expand All @@ -13031,7 +13050,7 @@ const renderSamplesMetadataAsideItems = async () => {
e.target.innerText.split("/")[0]
);

await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();
});
});
};
Expand Down Expand Up @@ -13711,7 +13730,7 @@ const guidedCreateOrRenameDataset = async (bfAccount, datasetName) => {
// so new metadata can be uploaded to the newly created dataset
// (This would happen if the user deleted the dataset on Pennsieve)
window.sodaJSONObj["previously-uploaded-data"] = {};
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();
}
}

Expand Down Expand Up @@ -13764,7 +13783,7 @@ const guidedCreateOrRenameDataset = async (bfAccount, datasetName) => {
//Save the dataset ID generated by pennsieve so the dataset is not re-uploaded when the user
//resumes progress after failing an upload
window.sodaJSONObj["digital-metadata"]["pennsieve-dataset-id"] = createdDatasetsID;
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();

return createdDatasetsID;
} catch (error) {
Expand Down Expand Up @@ -13830,7 +13849,7 @@ const guidedAddDatasetSubtitle = async (bfAccount, datasetName, datasetSubtitle)
datasetSubtitleUploadText.innerHTML = `Successfully added dataset subtitle: ${datasetSubtitle}`;
guidedUploadStatusIcon("guided-dataset-subtitle-upload-status", "success");
window.sodaJSONObj["previously-uploaded-data"]["subtitle"] = datasetSubtitle;
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();

// Send successful dataset subtitle upload event to Kombucha
window.electron.ipcRenderer.send(
Expand Down Expand Up @@ -13916,7 +13935,7 @@ const guidedAddDatasetDescription = async (
datasetDescriptionUploadText.innerHTML = `Successfully added dataset description!`;
guidedUploadStatusIcon("guided-dataset-description-upload-status", "success");
window.sodaJSONObj["previously-uploaded-data"]["description"] = description;
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();

// Send successful dataset description upload event to Kombucha
window.electron.ipcRenderer.send(
Expand Down Expand Up @@ -14003,7 +14022,7 @@ const uploadValidBannerImage = async (bfAccount, datasetName, bannerImagePath) =
datasetBannerImageUploadText.innerHTML = `Successfully added dataset banner image!`;
guidedUploadStatusIcon("guided-dataset-banner-image-upload-status", "success");
window.sodaJSONObj["previously-uploaded-data"]["banner-image-path"] = bannerImagePath;
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();

// Send successful banner image upload event to Kombucha
window.electron.ipcRenderer.send(
Expand Down Expand Up @@ -14096,7 +14115,7 @@ const guidedAddDatasetLicense = async (bfAccount, datasetName, datasetLicense) =
datasetLicenseUploadText.innerHTML = `Successfully added dataset license: ${datasetLicense}`;
guidedUploadStatusIcon("guided-dataset-license-upload-status", "success");
window.sodaJSONObj["previously-uploaded-data"]["license"] = datasetLicense;
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();

// Send successful license upload event to Kombucha
window.electron.ipcRenderer.send(
Expand Down Expand Up @@ -14169,7 +14188,7 @@ const guidedAddDatasetTags = async (bfAccount, datasetName, tags) => {
datasetTagsUploadText.innerHTML = `Successfully added dataset tags: ${tags.join(", ")}`;
guidedUploadStatusIcon("guided-dataset-tags-upload-status", "success");
window.sodaJSONObj["previously-uploaded-data"]["tags"] = tags;
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();

// Send successful tags upload event to Kombucha
window.electron.ipcRenderer.send(
Expand Down Expand Up @@ -15688,7 +15707,7 @@ const guidedUploadDatasetToPennsieve = async () => {
window.sodaJSONObj["digital-metadata"]["name"];

// Save the window.sodaJSONObj after a successful upload
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();

//Display the click next text
document.getElementById("guided--verify-files").classList.remove("hidden");
Expand Down Expand Up @@ -16493,8 +16512,6 @@ $("#guided-next-button").on("click", async function () {

try {
await savePageChanges(window.pageBeingLeftID);
//Save progress onto local storage with the dataset name as the key
await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);

//Mark page as completed in JSONObj so we know what pages to load when loading local saves
//(if it hasn't already been marked complete)
Expand Down Expand Up @@ -17087,7 +17104,7 @@ const saveSubPageChanges = async (openSubPageID) => {
"import";
}

await saveGuidedProgress(window.sodaJSONObj["digital-metadata"]["name"]);
await guidedSaveProgress();
} catch (error) {
guidedSetNavLoadingState(false);
throw error;
Expand Down
3 changes: 0 additions & 3 deletions src/renderer/src/scripts/organize-dataset/curate-functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -502,11 +502,8 @@ window.uploadDatasetClickHandler = async (ev) => {
};

window.handleLocalDatasetImport = async (path) => {
console.log("Importing local dataset from path:", path);
const list = await getFilesAndFolders(path);
console.log("List of files and folders:", list);
const currentFileExplorerPath = window.organizeDSglobalPath.value.trim();
console.log("Current file explorer path:", currentFileExplorerPath);
const builtDatasetStructure = await window.buildDatasetStructureJsonFromImportedData(
list.folders,
"dataset_root/", // Use dataset_root as the root folder since we are importing the root in this case
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/src/scripts/others/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4359,13 +4359,15 @@ const namesOfForbiddenFiles = {

const sparcFolderAndFileRegex = /[\+&\%#]/;
const identifierConventionsRegex = /^[a-zA-Z0-9-_]+$/;
const forbiddenCharacters = /[@#$%^&*()+=\/\\|"'~;:<>{}\[\]?]/;

window.evaluateStringAgainstSdsRequirements = (stringToTest, stringCase) => {
const testCases = {
"folder-and-file-name-is-valid": !sparcFolderAndFileRegex.test(stringToTest), // returns true if the string is valid
"file-is-hidden": stringToTest.startsWith("."), // returns true if the string is hidden
"file-is-in-forbidden-files-list": namesOfForbiddenFiles?.[stringToTest], // returns true if the string is in the forbidden files list
"string-adheres-to-identifier-conventions": identifierConventionsRegex.test(stringToTest), // returns true if the string adheres to the identifier conventions
"string-contains-forbidden-characters": forbiddenCharacters.test(stringToTest), // returns true if the string contains forbidden characters
};
return testCases[stringCase];
};
Expand Down

0 comments on commit 79642c6

Please sign in to comment.