Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 15.2.3 bug fix release #370

Merged
merged 7 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
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 Expand Up @@ -58,7 +65,7 @@
## Bug fixes:

- Fixed an issue where the standalone manifest generator fails to generate manifests due to the manifest_files directory not being cleared prior to generation.
- Fixed an issue where the cod eto fixe the upload failing was reverted prior to release.

Check failure on line 68 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / Check for spelling errors

fixe ==> fixed, fixes, fix, fixme, fixer

## v15.0.1 - 2024-05-30

Expand Down Expand Up @@ -106,7 +113,7 @@

## v13.1.3 - 2024-02-29

## Feature Addditions:

Check failure on line 116 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / Check for spelling errors

Addditions ==> Additions

- Announcements have been redesigned to convey updates and fixes clearly.
- Added the ability to generate a copy of a dataset's manifest files locally within the organize datasets feature.
Expand Down Expand Up @@ -137,7 +144,7 @@
## Feature Additions:

- Users can generate datasets on their computer/local device in Guided Mode without having to sign in with a Pennsieve account.
- Pennsieve API Key names are more unique to resolve myriad of issues that come from having multiple users on one computer and from having one user with acccounts across multiple computers.

Check failure on line 147 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / Check for spelling errors

acccounts ==> accounts
- Switching workspaces resets FFM UI to default state.

## Bug fixes:
Expand All @@ -148,7 +155,7 @@

## Feature Additions:

- SODA added the ability for users to generate a local copy of their datasets for review to Guided Mode. This should assist users in ensuring their dataset is organized per their criteria before commiting to uploading their dataset to Pennsieve.

Check failure on line 158 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / Check for spelling errors

commiting ==> committing
- SODA has been converted to ESM and is using Electron-Vite for bundling.

## v.12.5.0 - 2023-01-04
Expand Down Expand Up @@ -221,7 +228,7 @@
- Curate and Share button's icon has been updated to be more intuitive. Changing color when it is selected.
- Return to progress button that appears in the nav bar will correctly update the navigation menu depending where the user navigates.
- Move item pop up has a max height preventing users from endlessly scrolling to confirm their move.
- Disseminate calender does not hide anymore when checkbox to awknowledge sharing with the curation team. (Should only be modified by the embargo checkbox)

Check failure on line 231 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / Check for spelling errors

calender ==> calendar
- Sweet alert icons for Prepare Metadata -> No 'metadata' file found in root directory will all be the same icon.

## Removed:
Expand Down Expand Up @@ -372,7 +379,7 @@
- FFM: Imported metadata files not resetting upon changing a dataset has been patched.

- The ability for deleting all files selected has been fixed.
- Taxonomy endpoint has been patched to look up names and return response corrently.

Check failure on line 382 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / Check for spelling errors

corrently ==> correctly, currently

## Feature Additions:

Expand Down Expand Up @@ -456,7 +463,7 @@

## Bug fixes:

- Manual Windows build creation to fix an issue with the back-end not connectiong on Windows.

Check failure on line 466 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / Check for spelling errors

connectiong ==> connection, connecting

## v.9.4.0 - 2022-11-02

Expand Down Expand Up @@ -555,10 +562,10 @@
- Prepare Metadata - Create manifest.xlsx: Automated synchronization between manifest files and their Pennsieve dataset. E.g., if a file is removed from a dataset, the file's corresponding manifest file entry will be removed.
- Prepare Metadata - Create manifest.xlsx: Empty columns are dropped from manifest files once the user generates their files locally or on Pennsieve.
- Prepare Metadata - Create manifest.xlsx: Preview manifest files locally before they are uploaded to Pennsieve.
- Prepare Metadata - Create manifest.xlsx: Generate manfiest files locally in your directory of choice.

Check failure on line 565 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / Check for spelling errors

manfiest ==> manifest
- Guided Mode - added the ability to edit auto-generated manifest files in a spreadsheet like UI.
- Freeform Mode - Ability to add your dataset to a collection has been added. Intended to better group datasets.
- Image optimzation for banner images. Image sizes that exceed over 2048 x 2048 will be prompted to scale the image accordingly for upload.

Check failure on line 568 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / Check for spelling errors

optimzation ==> optimization

## 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) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider consolidating duplicate save operations and simplifying async flow patterns.

The code has accumulated unnecessary complexity that can be simplified while maintaining functionality:

  1. Consolidate duplicate save functions:
// Remove saveGuidedProgress and update guidedSaveProgress
const guidedSaveProgress = async () => {
  const fileName = window.sodaJSONObj?.["digital-metadata"]?.["name"];
  if (!fileName || typeof fileName !== "string" || !fileName.length) {
    return;
  }

  window.sodaJSONObj["last-modified"] = new Date();
  const currentVersion = document.getElementById("version").innerHTML;
  window.sodaJSONObj["last-version-of-soda-used"] = currentVersion;

  try {
    await window.fs.mkdir(guidedProgressFilePath, { recursive: true });
    await window.fs.writeFile(
      guidedFilePath, 
      JSON.stringify(window.sodaJSONObj, null, 2)
    );
  } catch (error) {
    window.log.error(error);
    throw error;
  }
};
  1. Remove unnecessary async conversion:
const guidedGetPageToReturnTo = (sodaJSONObj) => {
  const firstPageID = getNonSkippedGuidedModePages(document)[0].id;

  if (window.sodaJSONObj["previous-guided-upload-dataset-name"]) {
    return "guided-dataset-dissemination-tab";
  }

  const currentVersion = document.getElementById("version").innerHTML;
  if (window.sodaJSONObj["last-version-of-soda-used"] !== currentVersion) {
    // Show version change message where needed, e.g. in openPage
    return firstPageID;
  }

  return window.sodaJSONObj["page-before-exit"] || firstPageID;
};

These changes simplify the code by:

  • Eliminating duplicate save functions
  • Removing unnecessary async/await
  • Centralizing error handling
  • Making the code flow more linear and easier to follow

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
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
Loading