diff --git a/.eslintrc.json b/.eslintrc.json index 018ae8270ee..c47227870ea 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -18,6 +18,21 @@ "plugin:i18next/recommended", "plugin:tailwindcss/recommended" ], + "overrides": [ + { + "files": [ + "**/*.mdx" + ], + "extends": [ + "plugin:react/recommended", + "plugin:mdx/recommended" + ], + "rules": { + "react/jsx-no-target-blank": "off", + "i18next/no-literal-string": "off" + } + } + ], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaFeatures": { @@ -72,7 +87,6 @@ "*.res", "*.css", "*.csv", - "*.stories.mdx", "Dockerfile" ] } diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml new file mode 100644 index 00000000000..ce4bd271cf7 --- /dev/null +++ b/.github/workflows/linter.yml @@ -0,0 +1,31 @@ +name: Lint Code Base + +on: + pull_request: + branches: + - develop + - master + merge_group: + +jobs: + lint: + runs-on: ubuntu-latest + permissions: + contents: read + packages: read + statuses: write + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: "18" + + - name: Install dependencies + run: npm ci + + - name: Run lint + run: npm run lint -- --quiet diff --git a/cypress/e2e/assets_spec/asset_homepage.cy.ts b/cypress/e2e/assets_spec/asset_homepage.cy.ts index 8bc24c7370f..61f7d8a52c0 100644 --- a/cypress/e2e/assets_spec/asset_homepage.cy.ts +++ b/cypress/e2e/assets_spec/asset_homepage.cy.ts @@ -73,7 +73,7 @@ describe("Asset Tab", () => { assetFilters.assertAssetTypeText("INTERNAL"); assetFilters.assertAssetClassText("ONVIF"); assetFilters.assertStatusText("ACTIVE"); - assetFilters.assertLocationText("Camera Locations"); + assetFilters.assertLocationText("Camera Loc"); assetFilters.clickadvancefilter(); assetFilters.clearFilters(); }); @@ -92,7 +92,6 @@ describe("Asset Tab", () => { assetPage.importAssetFile(); assetPage.selectImportLocation("Camera Locations"); assetPage.clickImportAsset(); - assetPage.verifySuccessNotification("Assets imported successfully"); }); it("verify imported asset", () => { diff --git a/cypress/e2e/assets_spec/assets_manage.cy.ts b/cypress/e2e/assets_spec/assets_manage.cy.ts index 34c554b374e..8b440f68761 100644 --- a/cypress/e2e/assets_spec/assets_manage.cy.ts +++ b/cypress/e2e/assets_spec/assets_manage.cy.ts @@ -5,6 +5,12 @@ import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; import FacilityPage from "../../pageobject/Facility/FacilityCreation"; import { AssetFilters } from "../../pageobject/Asset/AssetFilters"; +function addDaysToDate(numberOfDays: number) { + const inputDate = new Date(); + inputDate.setDate(inputDate.getDate() + numberOfDays); + return inputDate.toISOString().split("T")[0]; +} + describe("Asset", () => { const assetPage = new AssetPage(); const loginPage = new LoginPage(); @@ -26,6 +32,33 @@ describe("Asset", () => { cy.awaitUrl("/assets"); }); + it("Verify Asset Warranty Expiry Label", () => { + assetSearchPage.typeSearchKeyword(assetname); + assetSearchPage.pressEnter(); + assetSearchPage.verifyBadgeContent(assetname); + assetSearchPage.clickAssetByName(assetname); + assetPage.clickupdatedetailbutton(); + assetPage.scrollintoWarrantyDetails(); + assetPage.enterWarrantyExpiryDate(addDaysToDate(100)); // greater than 3 months + assetPage.clickassetupdatebutton(); + assetPage.verifyWarrantyExpiryLabel(""); + assetPage.clickupdatedetailbutton(); + assetPage.scrollintoWarrantyDetails(); + assetPage.enterWarrantyExpiryDate(addDaysToDate(80)); // less than 3 months + assetPage.clickassetupdatebutton(); + assetPage.verifyWarrantyExpiryLabel("3 months"); + assetPage.clickupdatedetailbutton(); + assetPage.scrollintoWarrantyDetails(); + assetPage.enterWarrantyExpiryDate(addDaysToDate(20)); // less than 1 month + assetPage.clickassetupdatebutton(); + assetPage.verifyWarrantyExpiryLabel("1 month"); + assetPage.clickupdatedetailbutton(); + assetPage.scrollintoWarrantyDetails(); + assetPage.enterWarrantyExpiryDate(addDaysToDate(100)); // check for greater than 3 months again to verify the label is removed + assetPage.clickassetupdatebutton(); + assetPage.verifyWarrantyExpiryLabel(""); + }); + it("Create & Edit a service history and verify reflection", () => { assetSearchPage.typeSearchKeyword(assetname); assetSearchPage.pressEnter(); diff --git a/cypress/e2e/facility_spec/locations.cy.ts b/cypress/e2e/facility_spec/locations.cy.ts index d5b3cc9990f..cac9adbdde1 100644 --- a/cypress/e2e/facility_spec/locations.cy.ts +++ b/cypress/e2e/facility_spec/locations.cy.ts @@ -13,6 +13,7 @@ describe("Location Management Section", () => { cy.intercept("GET", "**/api/v1/facility/**").as("getFacilities"); cy.get("[id='facility-details']").first().click(); cy.wait("@getFacilities").its("response.statusCode").should("eq", 200); + cy.get("h1.text-3xl.font-bold", { timeout: 10000 }).should("be.visible"); cy.get("#manage-facility-dropdown button").should("be.visible"); cy.get("[id='manage-facility-dropdown']").scrollIntoView().click(); cy.get("[id=location-management]").click(); diff --git a/cypress/e2e/patient_spec/patient_crud.cy.ts b/cypress/e2e/patient_spec/patient_crud.cy.ts index fcfd97039f7..4fef861aeab 100644 --- a/cypress/e2e/patient_spec/patient_crud.cy.ts +++ b/cypress/e2e/patient_spec/patient_crud.cy.ts @@ -130,12 +130,27 @@ describe("Patient Creation with consultation", () => { patientConsultationPage.interceptMediaBase(); patientConsultationPage.selectMedicinebox(); patientConsultationPage.waitForMediabaseStatusCode(); - patientConsultationPage.prescribeMedicine(); + patientConsultationPage.prescribefirstMedicine(); patientConsultationPage.enterDosage("3"); patientConsultationPage.selectDosageFrequency("Twice daily"); patientConsultationPage.submitPrescriptionAndReturn(); }); + it("Edit created consultation to existing patient", () => { + updatePatientPage.visitUpdatedPatient(); + patientConsultationPage.visitEditConsultationPage(); + patientConsultationPage.fillIllnessHistory("editted"); + patientConsultationPage.selectConsultationStatus( + "Referred from other hospital" + ); + patientConsultationPage.updateSymptoms("FEVER"); + patientConsultationPage.setSymptomsDate("01082023"); + patientConsultationPage.updateConsultation(); + patientConsultationPage.verifySuccessNotification( + "Consultation updated successfully" + ); + }); + afterEach(() => { cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/patient_manage.cy.ts b/cypress/e2e/patient_spec/patient_manage.cy.ts new file mode 100644 index 00000000000..e8d381286aa --- /dev/null +++ b/cypress/e2e/patient_spec/patient_manage.cy.ts @@ -0,0 +1,78 @@ +import { afterEach, before, beforeEach, cy, describe, it } from "local-cypress"; +import LoginPage from "../../pageobject/Login/LoginPage"; +import { PatientConsultationPage } from "../../pageobject/Patient/PatientConsultation"; +import { PatientPage } from "../../pageobject/Patient/PatientCreation"; + +describe("Patient", () => { + const loginPage = new LoginPage(); + const patientPage = new PatientPage(); + const patientConsultationPage = new PatientConsultationPage(); + + before(() => { + loginPage.loginAsDisctrictAdmin(); + cy.saveLocalStorage(); + }); + + beforeEach(() => { + cy.restoreLocalStorage(); + cy.awaitUrl("/patients"); + }); + + // it("Create Patient shift requests.", () => { + // patientPage.visitPatient(); + // patientConsultationPage.visitShiftRequestPage(); + // patientConsultationPage.enterPatientShiftDetails( + // "Test User", + // phone_number, + // "Dummy Shifting", + // "Reason" + // ); + // patientConsultationPage.createShiftRequest(); + // patientConsultationPage.verifySuccessNotification( + // "Shift request created successfully" + // ); + // }); + // commented out the shifting request, as logic need to be re-visited + + it("Post doctor notes for an already created patient", () => { + patientPage.visitPatient(); + patientConsultationPage.visitDoctorNotesPage(); + patientConsultationPage.addDoctorsNotes("Test Doctor Notes"); + patientConsultationPage.postDoctorNotes(); + patientConsultationPage.verifySuccessNotification( + "Note added successfully" + ); + }); + + it("Edit prescription for an already created patient", () => { + patientPage.visitPatient(); + patientConsultationPage.visitEditPrescriptionPage(); + patientConsultationPage.clickAddPrescription(); + patientConsultationPage.interceptMediaBase(); + patientConsultationPage.selectMedicinebox(); + patientConsultationPage.waitForMediabaseStatusCode(); + patientConsultationPage.prescribesecondMedicine(); + patientConsultationPage.enterDosage("4"); + patientConsultationPage.selectDosageFrequency("Twice daily"); + patientConsultationPage.submitPrescription(); + }); + + it("Upload consultations file ", () => { + patientPage.visitPatient(); + patientConsultationPage.visitFilesPage(); + patientConsultationPage.uploadFile(); + patientConsultationPage.clickUploadFile(); + }); + + it("Discharge a patient", () => { + patientPage.visitPatient(); + patientConsultationPage.clickDischargePatient(); + patientConsultationPage.selectDischargeReason("Recovered"); + patientConsultationPage.addDischargeNotes("Discharge notes"); + patientConsultationPage.confirmDischarge(); + }); + + afterEach(() => { + cy.saveLocalStorage(); + }); +}); diff --git a/cypress/e2e/users_spec/user_creation.cy.ts b/cypress/e2e/users_spec/user_creation.cy.ts new file mode 100644 index 00000000000..ae416d8d990 --- /dev/null +++ b/cypress/e2e/users_spec/user_creation.cy.ts @@ -0,0 +1,197 @@ +import { cy, describe, before, beforeEach, it, afterEach } from "local-cypress"; +import LoginPage from "../../pageobject/Login/LoginPage"; +import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; +import FacilityPage from "../../pageobject/Facility/FacilityCreation"; +import { UserPage } from "../../pageobject/Users/UserSearch"; +import { UserCreationPage } from "../../pageobject/Users/UserCreation"; + +describe("User Creation", () => { + const userPage = new UserPage(); + const loginPage = new LoginPage(); + const userCreationPage = new UserCreationPage(); + const facilityPage = new FacilityPage(); + const assetSearchPage = new AssetSearchPage(); + const fillFacilityName = "Dummy Facility 1"; + const makeid = (length: number) => { + let result = ""; + const characters = "abcdefghijklmnopqrstuvwxyz0123456789"; + const charactersLength = characters.length; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; + }; + const username = makeid(25); + const alreadylinkedusersviews = [ + "devdoctor", + "devstaff2", + "devdistrictadmin", + ]; + const EXPECTED_ERROR_MESSAGES = [ + "Please select the User Type", + "Please enter valid phone number", + "Please enter the username", + "Please enter date in YYYY/MM/DD format", + "Please enter the password", + "Confirm password is required", + "First Name is required", + "Last Name is required", + "Please enter a valid email address", + "Please select the Gender", + "Please select the state", + "Please select the district", + "Please select the local body", + ]; + + before(() => { + loginPage.loginAsDisctrictAdmin(); + cy.saveLocalStorage(); + }); + + beforeEach(() => { + cy.restoreLocalStorage(); + cy.awaitUrl("/users"); + }); + + it("create new user and verify reflection", () => { + userCreationPage.clickElementById("addUserButton"); + userCreationPage.selectFacility("Dummy Shifting Center"); + userCreationPage.typeIntoElementById("username", username); + userCreationPage.typeIntoElementById("password", "Test@123"); + userCreationPage.selectHomeFacility("Dummy Shifting Center"); + userCreationPage.typeIntoElementById("phone_number", "9999999999"); + userCreationPage.setInputDate("date_of_birth", "date-input", "25081999"); + userCreationPage.selectDropdownOption("user_type", "Doctor"); + userCreationPage.typeIntoElementById("c_password", "Test@123"); + userCreationPage.typeIntoElementById("doctor_qualification", "MBBS"); + userCreationPage.typeIntoElementById("doctor_experience_commenced_on", "2"); + userCreationPage.typeIntoElementById( + "doctor_medical_council_registration", + "123456789" + ); + userCreationPage.typeIntoElementById("first_name", "cypress test"); + userCreationPage.typeIntoElementById("last_name", "staff user"); + userCreationPage.typeIntoElementById("email", "test@test.com"); + userCreationPage.selectDropdownOption("gender", "Male"); + userCreationPage.selectDropdownOption("state", "Kerala"); + userCreationPage.selectDropdownOption("district", "Ernakulam"); + userCreationPage.clickElementById("submit"); + userCreationPage.verifyNotification("User added successfully"); + userPage.typeInSearchInput(username); + userPage.checkUsernameText(username); + userCreationPage.verifyElementContainsText("name", "cypress test"); + userCreationPage.verifyElementContainsText("role", "Doctor"); + userCreationPage.verifyElementContainsText("district", "Ernakulam"); + userCreationPage.verifyElementContainsText( + "home_facility", + "Dummy Shifting Center" + ); + userCreationPage.verifyElementContainsText("doctor-qualification", "MBBS"); + userCreationPage.verifyElementContainsText("doctor-experience", "2"); + userCreationPage.verifyElementContainsText( + "medical-council-registration", + "123456789" + ); + }); + + it("create new user form throwing mandatory field error", () => { + userCreationPage.clickElementById("addUserButton"); + userCreationPage.clickElementById("submit"); + userCreationPage.verifyErrorMessages(EXPECTED_ERROR_MESSAGES); + }); + + it("view user redirection from facility page", () => { + cy.visit("/facility"); + assetSearchPage.typeSearchKeyword(fillFacilityName); + assetSearchPage.pressEnter(); + facilityPage.verifyFacilityBadgeContent(fillFacilityName); + facilityPage.visitAlreadyCreatedFacility(); + facilityPage.clickManageFacilityDropdown(); + facilityPage.clickViewUsersOption(); + userPage.verifyMultipleBadgesWithSameId(alreadylinkedusersviews); + }); + + // the below commented out codes, will be used in the upcoming refactoring of this module, since it is a inter-dependent of partially converted code, currently taking it down + + // it("link facility for user", () => { + // cy.contains("Linked Facilities").click(); + // cy.intercept(/\/api\/v1\/facility/).as("getFacilities"); + // cy.get("[name='facility']") + // .click() + // .type("Dummy Facility 1") + // .wait("@getFacilities"); + // cy.get("li[role='option']").first().click(); + // cy.intercept(/\/api\/v1\/users\/\w+\/add_facility\//).as("addFacility"); + // cy.get("button[id='link-facility']").click(); + // cy.wait("@addFacility") + // // .its("response.statusCode") + // // .should("eq", 201) + // .get("span") + // .contains("Facility - User Already has permission to this facility"); + // }); + + // describe("Edit User Profile & Error Validation", () => { + // before(() => { + // cy.loginByApi(username, "#@Cypress_test123"); + // cy.saveLocalStorage(); + // }); + + // beforeEach(() => { + // cy.restoreLocalStorage(); + // cy.awaitUrl("/user/profile"); + // cy.contains("button", "Edit User Profile").click(); + // }); + + // it("First name Field Updation " + username, () => { + // cy.get("input[name=firstName]").clear(); + // cy.contains("button[type='submit']", "Update").click(); + // cy.get("span.error-text").should("contain", "Field is required"); + // cy.get("input[name=firstName]").type("firstName updated"); + // cy.contains("button[type='submit']", "Update").click(); + // }); + + // it("Last name Field Updation " + username, () => { + // cy.get("input[name=lastName]").clear(); + // cy.contains("button[type='submit']", "Update").click(); + // cy.get("span.error-text").should("contain", "Field is required"); + // cy.get("input[name=lastName]").type("lastName updated"); + // cy.contains("button[type='submit']", "Update").click(); + // }); + + // it("Age Field Updation " + username, () => { + // cy.get("input[name=age]").clear(); + // cy.contains("button[type='submit']", "Update").click(); + // cy.get("span.error-text").should("contain", "This field is required"); + // cy.get("input[name=age]").type("11"); + // cy.contains("button[type='submit']", "Update").click(); + // }); + + // it("Phone number Field Updation " + username, () => { + // cy.get("input[name=phoneNumber]").clear(); + // cy.contains("button[type='submit']", "Update").click(); + // cy.get("span.error-text").should( + // "contain", + // "Please enter valid phone number" + // ); + // cy.get("input[name=phoneNumber]").type("+919999999999"); + // cy.contains("button[type='submit']", "Update").click(); + // }); + + // it("Whatsapp number Field Updation " + username, () => { + // cy.get("input[name=altPhoneNumber]").clear(); + // cy.get("input[name=altPhoneNumber]").type("+919999999999"); + // cy.contains("button[type='submit']", "Update").click(); + // }); + + // it("Email Field Updation " + username, () => { + // cy.get("input[name=email]").clear(); + // cy.contains("button[type='submit']", "Update").click(); + // cy.get("span.error-text").should("contain", "This field is required"); + // cy.get("input[name=email]").type("test@test.com"); + // cy.contains("button[type='submit']", "Update").click(); + // }); + + afterEach(() => { + cy.saveLocalStorage(); + }); +}); diff --git a/cypress/e2e/users_spec/user_crud.cy.ts b/cypress/e2e/users_spec/user_crud.cy.ts deleted file mode 100644 index 41a12a891a8..00000000000 --- a/cypress/e2e/users_spec/user_crud.cy.ts +++ /dev/null @@ -1,207 +0,0 @@ -import { afterEach, before, beforeEach, cy, describe, it } from "local-cypress"; - -const makeid = (length: number) => { - let result = ""; - const characters = "abcdefghijklmnopqrstuvwxyz0123456789"; - const charactersLength = characters.length; - for (let i = 0; i < length; i++) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); - } - return result; -}; - -const username = makeid(25); -const phone_number = 9999999999; -const alt_phone_number = 9999999999; - -describe("User management", () => { - before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); - cy.saveLocalStorage(); - }); - - beforeEach(() => { - cy.restoreLocalStorage(); - cy.awaitUrl("/user"); - }); - - it("create user", () => { - cy.contains("Add New User").click(); - cy.get("[id='user_type'] > div > button").click(); - cy.get("div").contains("Ward Admin").click(); - cy.get("[id='state'] > div > button").click(); - cy.get("div").contains("Kerala").click(); - cy.get("[id='district'] > div > button").click(); - cy.get("div").contains("Ernakulam").click(); - cy.get("[id='local_body'] > div > button").click(); - cy.get("div").contains("Aikaranad").click(); - cy.intercept(/\/api\/v1\/facility/).as("facility"); - cy.get("[name='facilities']") - .click() - .type("Dummy Facility 1") - .wait("@facility"); - cy.get("li[role='option']").first().click(); - cy.get("input[type='checkbox']").click(); - cy.get("[name='phone_number']").type(phone_number); - cy.get("[name='alt_phone_number']").type(alt_phone_number); - cy.intercept(/users/).as("check_availability"); - cy.get("#date_of_birth").should("be.visible").click(); - cy.get("#date-input").click().type("25081999"); - cy.get("[name='username']").type(username); - cy.wait("@check_availability").its("response.statusCode").should("eq", 200); - cy.get("[name='password']").type("#@Cypress_test123"); - cy.get("[name='c_password']").type("#@Cypress_test123"); - cy.get("[name='first_name']").type("Cypress Test"); - cy.get("[name='last_name']").type("Tester"); - cy.get("[name='email']").type("cypress@tester.com"); - cy.get("[id='gender'] > div > button").click(); - cy.get("div").contains("Male").click(); - cy.get("button[id='submit']").contains("Save User").click(); - cy.verifyNotification("User added successfully"); - }); - - it("view user and verify details", () => { - cy.contains("Advanced Filters").click(); - cy.get("[name='first_name']").type("Cypress Test"); - cy.get("[name='last_name']").type("Tester"); - cy.get("#role button").click(); - cy.contains("#role li", "Ward Admin").click(); - cy.get("input[name='district']").click(); - cy.get("input[name='district']").type("Ernakulam"); - cy.get("li[id^='headlessui-combobox-option']") - .contains("Ernakulam") - .click(); - cy.get("[placeholder='Phone Number']").click(); - cy.get("[placeholder='Phone Number']").type(phone_number); - cy.get("[placeholder='WhatsApp Phone Number']").type(alt_phone_number); - cy.contains("Apply").click(); - cy.intercept(/\/api\/v1\/users/).as("getUsers"); - cy.wait(1000); - cy.get("[name='username']").type(username); - cy.wait("@getUsers"); - cy.get("dd[id='count']").contains(/^1$/).click(); - cy.get("div[id='usr_0']").within(() => { - cy.intercept(`/api/v1/users/${username}/get_facilities/`).as( - "userFacility" - ); - cy.get("div[id='role']").contains(/^WardAdmin$/); - cy.get("div[id='name']").contains("Cypress Test Tester"); - cy.get("div[id='district']").contains(/^Ernakulam$/); - cy.get("div[id='local_body']").contains("Aikaranad"); - cy.get("div[id='created_by']").contains(/^devdistrictadmin$/); - cy.get("div[id='home_facility']").contains("No Home Facility"); - cy.get("button[id='facilities']").click(); - cy.wait("@userFacility") - .getAttached("div[id=facility_0] > div > span") - .contains("Dummy Facility 1"); - }); - }); - - it("link facility for user", () => { - cy.contains("Linked Facilities").click(); - cy.intercept(/\/api\/v1\/facility/).as("getFacilities"); - cy.get("[name='facility']") - .click() - .type("Dummy Facility 1") - .wait("@getFacilities"); - cy.get("li[role='option']").first().click(); - cy.intercept(/\/api\/v1\/users\/\w+\/add_facility\//).as("addFacility"); - cy.get("button[id='link-facility']").click(); - cy.wait("@addFacility") - // .its("response.statusCode") - // .should("eq", 201) - .get("span") - .contains("Facility - User Already has permission to this facility"); - }); - - it("Next/Previous Page", () => { - // only works for desktop mode - cy.get("button#next-pages").click(); - cy.url().should("include", "page=2"); - cy.get("button#prev-pages").click(); - cy.url().should("include", "page=1"); - }); - - afterEach(() => { - cy.saveLocalStorage(); - }); -}); - -describe("Edit User Profile & Error Validation", () => { - before(() => { - cy.loginByApi(username, "#@Cypress_test123"); - cy.saveLocalStorage(); - }); - - beforeEach(() => { - cy.restoreLocalStorage(); - cy.awaitUrl("/user/profile"); - cy.contains("button", "Edit User Profile").click(); - }); - - it("First name Field Updation " + username, () => { - cy.get("input[name=firstName]").clear(); - cy.contains("button[type='submit']", "Update").click(); - cy.get("span.error-text").should("contain", "Field is required"); - cy.get("input[name=firstName]").type("firstName updated"); - cy.contains("button[type='submit']", "Update").click(); - }); - - it("Last name Field Updation " + username, () => { - cy.get("input[name=lastName]").clear(); - cy.contains("button[type='submit']", "Update").click(); - cy.get("span.error-text").should("contain", "Field is required"); - cy.get("input[name=lastName]").type("lastName updated"); - cy.contains("button[type='submit']", "Update").click(); - }); - - it("Age Field Updation " + username, () => { - cy.get("input[name=age]").clear(); - cy.contains("button[type='submit']", "Update").click(); - cy.get("span.error-text").should("contain", "This field is required"); - cy.get("input[name=age]").type("11"); - cy.contains("button[type='submit']", "Update").click(); - }); - - it("Phone number Field Updation " + username, () => { - cy.get("input[name=phoneNumber]").clear(); - cy.contains("button[type='submit']", "Update").click(); - cy.get("span.error-text").should( - "contain", - "Please enter valid phone number" - ); - cy.get("input[name=phoneNumber]").type("+919999999999"); - cy.contains("button[type='submit']", "Update").click(); - }); - - it("Whatsapp number Field Updation " + username, () => { - cy.get("input[name=altPhoneNumber]").clear(); - cy.get("input[name=altPhoneNumber]").type("+919999999999"); - cy.contains("button[type='submit']", "Update").click(); - }); - - it("Email Field Updation " + username, () => { - cy.get("input[name=email]").clear(); - cy.contains("button[type='submit']", "Update").click(); - cy.get("span.error-text").should("contain", "This field is required"); - cy.get("input[name=email]").type("test@test.com"); - cy.contains("button[type='submit']", "Update").click(); - }); - - afterEach(() => { - cy.saveLocalStorage(); - }); -}); - -// describe("Delete User", () => { district admin wont be able to delete user -// it("deletes user", () => { -// cy.loginByApi("devdistrictadmin", "Coronasafe@123"); -// cy.awaitUrl("/user"); -// cy.get("[name='username']").type(username); -// cy.get("button") -// .should("contain", "Delete") -// .contains("Delete") -// .click(); -// cy.get("button.font-medium.btn.btn-danger").click(); -// }); -// }); diff --git a/cypress/e2e/users_spec/user_homepage.cy.ts b/cypress/e2e/users_spec/user_homepage.cy.ts new file mode 100644 index 00000000000..060132105e6 --- /dev/null +++ b/cypress/e2e/users_spec/user_homepage.cy.ts @@ -0,0 +1,82 @@ +/// + +import { cy, describe, before, beforeEach, it, afterEach } from "local-cypress"; +import LoginPage from "../../pageobject/Login/LoginPage"; +import { UserPage } from "../../pageobject/Users/UserSearch"; + +describe("User Homepage", () => { + const userPage = new UserPage(); + const usernameToTest = "devdoctor"; + const currentuser = "devdistrictadmin"; + const loginPage = new LoginPage(); + const phone_number = "9876543219"; + const alt_phone_number = "9876543219"; + + before(() => { + loginPage.loginAsDisctrictAdmin(); + cy.saveLocalStorage(); + }); + + beforeEach(() => { + cy.restoreLocalStorage(); + cy.awaitUrl("/users"); + }); + + it("User advance filter functionality", () => { + userPage.clickAdvancedFilters(); + userPage.typeInFirstName("Dev"); + userPage.typeInLastName("Doctor"); + userPage.selectRole("Doctor"); + userPage.selectDistrict("Ernakulam"); + userPage.typeInPhoneNumber(phone_number); + userPage.typeInAltPhoneNumber(alt_phone_number); + userPage.applyFilter(); + userPage.verifyUrlafteradvancefilter(); + userPage.checkUsernameText(usernameToTest); + userPage.verifyDataTestIdText("First Name", "First Name: Dev"); + userPage.verifyDataTestIdText("Last Name", "Last Name: Doctor"); + userPage.verifyDataTestIdText( + "Phone Number", + "Phone Number: +919876543219" + ); + userPage.verifyDataTestIdText( + "WhatsApp no.", + "WhatsApp no.: +919876543219" + ); + userPage.verifyDataTestIdText("Role", "Role: Doctor"); + userPage.verifyDataTestIdText("District", "District: Ernakulam"); + userPage.clearFilters(); + userPage.verifyDataTestIdNotVisible("First Name"); + userPage.verifyDataTestIdNotVisible("Last Name"); + userPage.verifyDataTestIdNotVisible("Phone Number"); + userPage.verifyDataTestIdNotVisible("WhatsApp no."); + userPage.verifyDataTestIdNotVisible("Role"); + userPage.verifyDataTestIdNotVisible("District"); + }); + + it("Search by username", () => { + userPage.checkSearchInputVisibility(); + userPage.typeInSearchInput(usernameToTest); + userPage.checkUrlForUsername(usernameToTest); + userPage.checkUsernameText(usernameToTest); + userPage.checkUsernameBadgeVisibility(true); + userPage.clearSearchInput(); + userPage.checkUsernameBadgeVisibility(false); + userPage.typeInSearchInput(usernameToTest); + userPage.checkUsernameText(usernameToTest); + userPage.clickRemoveIcon(); + userPage.checkUsernameBadgeVisibility(false); + userPage.checkUsernameText(currentuser); + }); + + it("Next/Previous Page Navigation", () => { + userPage.navigateToNextPage(); + userPage.verifyCurrentPageNumber(2); + userPage.navigateToPreviousPage(); + userPage.verifyCurrentPageNumber(1); + }); + + afterEach(() => { + cy.saveLocalStorage(); + }); +}); diff --git a/cypress/fixtures/sampleAsset.xlsx b/cypress/fixtures/sampleAsset.xlsx index f8e234ce447..49421f62bac 100644 Binary files a/cypress/fixtures/sampleAsset.xlsx and b/cypress/fixtures/sampleAsset.xlsx differ diff --git a/cypress/pageobject/Asset/AssetCreation.ts b/cypress/pageobject/Asset/AssetCreation.ts index 45356a1a4e7..93bbc87c9ab 100644 --- a/cypress/pageobject/Asset/AssetCreation.ts +++ b/cypress/pageobject/Asset/AssetCreation.ts @@ -150,7 +150,7 @@ export class AssetPage { configureVitalAsset(hostName: string, localIp: string) { cy.get("[data-testid=asset-configure-button]").click(); - cy.get("#middlewareHostname").type(hostName); + cy.get("#middleware_hostname").type(hostName); cy.get("#localipAddress").type(localIp); } @@ -285,16 +285,39 @@ export class AssetPage { cy.get("#notes").scrollIntoView(); } - enterAssetNotes(text) { + enterAssetNotes(text: string) { cy.get("#notes").click().clear(); cy.get("#notes").click().type(text); } - enterAssetservicedate(text) { + enterAssetservicedate(text: string) { cy.get("input[name='last_serviced_on']").click(); cy.get("#date-input").click().type(text); } + scrollintoWarrantyDetails() { + cy.get("#warranty-details").scrollIntoView(); + } + + enterWarrantyExpiryDate(text: string) { + cy.get("#WarrantyAMCExpiry").click(); + cy.get("#WarrantyAMCExpiry").click().type(text); + } + + verifyWarrantyExpiryLabel(duration: string) { + if (duration === "") { + cy.get("#warranty-amc-expired-red").should("not.exist"); + cy.get("#warranty-amc-expiring-soon-orange").should("not.exist"); + cy.get("#warranty-amc-expiring-soon-yellow").should("not.exist"); + } else if (duration === "expired") { + cy.get("#warranty-amc-expired-red").should("be.visible"); + } else if (duration === "1 month") { + cy.get("#warranty-amc-expiring-soon-orange").should("be.visible"); + } else if (duration === "3 months") { + cy.get("#warranty-amc-expiring-soon-yellow").should("be.visible"); + } + } + clickassetupdatebutton() { cy.get("#submit").click(); } diff --git a/cypress/pageobject/Facility/FacilityCreation.ts b/cypress/pageobject/Facility/FacilityCreation.ts index 42ec6d8fd7c..d27433f04e7 100644 --- a/cypress/pageobject/Facility/FacilityCreation.ts +++ b/cypress/pageobject/Facility/FacilityCreation.ts @@ -106,6 +106,7 @@ class FacilityPage { } clickManageFacilityDropdown() { + cy.get("h1.text-3xl.font-bold", { timeout: 20000 }).should("be.visible"); cy.get("#manage-facility-dropdown button").scrollIntoView(); cy.get("#manage-facility-dropdown button") .contains("Manage Facility") @@ -128,6 +129,10 @@ class FacilityPage { cy.get("#view-assets").contains("View Assets").click(); } + clickViewUsersOption() { + cy.get("#view-users").click(); + } + clickInventoryManagementOption() { cy.get("#inventory-management", { timeout: 10000 }).should("be.visible"); cy.get("#inventory-management").click(); @@ -198,8 +203,6 @@ class FacilityPage { cy.intercept("GET", "**/api/v1/facility/**").as("getManagePage"); cy.go("back"); cy.wait("@getManagePage").its("response.statusCode").should("eq", 200); - cy.get("#manage-facility-dropdown").scrollIntoView(); - cy.get("#manage-facility-dropdown").should("exist"); } verifyfacilityviewassetredirection() { diff --git a/cypress/pageobject/Patient/PatientConsultation.ts b/cypress/pageobject/Patient/PatientConsultation.ts index 6937559d548..bf301641898 100644 --- a/cypress/pageobject/Patient/PatientConsultation.ts +++ b/cypress/pageobject/Patient/PatientConsultation.ts @@ -1,5 +1,7 @@ export class PatientConsultationPage { selectConsultationStatus(status: string) { + cy.get("#consultation_status").scrollIntoView(); + cy.get("#consultation_status").should("be.visible"); cy.get("#consultation_status") .click() .then(() => { @@ -49,7 +51,7 @@ export class PatientConsultationPage { .click() .type("1A"); cy.get("#icd11_diagnoses_object [role='option']") - .contains("1A03 Intestinal infections due to Escherichia coli") + .contains("1A00 Cholera") .scrollIntoView() .click(); cy.get("label[for='icd11_diagnoses_object']").click(); @@ -57,7 +59,7 @@ export class PatientConsultationPage { cy.get("#icd11_principal_diagnosis [role='combobox']").click().type("1A"); cy.get("#icd11_principal_diagnosis [role='option']") - .contains("1A03 Intestinal infections due to Escherichia coli") + .contains("1A00 Cholera") .click(); cy.get("#consultation_notes").click().type(consulationNotes); @@ -83,10 +85,18 @@ export class PatientConsultationPage { cy.intercept("GET", "**/api/v1/medibase/**").as("getMediaBase"); } - prescribeMedicine() { + prescribefirstMedicine() { cy.get("div#medicine_object input[placeholder='Select'][role='combobox']") .click() - .type("dolo{enter}"); + .type("dolo") + .type("{downarrow}{enter}"); + } + + prescribesecondMedicine() { + cy.get("div#medicine_object input[placeholder='Select'][role='combobox']") + .click() + .type("dolo") + .type("{downarrow}{downarrow}{enter}"); } selectMedicinebox() { @@ -95,6 +105,23 @@ export class PatientConsultationPage { ).click(); } + visitFilesPage() { + cy.get("a").contains("Files").click(); + } + + uploadFile() { + cy.get("#file_upload_patient").selectFile( + "cypress/fixtures/sampleAsset.xlsx", + { force: true } + ); + } + + clickUploadFile() { + cy.intercept("POST", "**/api/v1/files/").as("uploadFile"); + cy.get("#upload_file_button").click(); + cy.wait("@uploadFile").its("response.statusCode").should("eq", 201); + } + waitForMediabaseStatusCode() { cy.wait("@getMediaBase").its("response.statusCode").should("eq", 200); } @@ -119,4 +146,119 @@ export class PatientConsultationPage { cy.get("[data-testid='return-to-patient-dashboard']").click(); cy.wait("@submitPrescription").its("response.statusCode").should("eq", 201); } + + visitEditConsultationPage() { + cy.get("#view_consulation_updates").click(); + cy.get("button").contains("Edit Consultation Details").click(); + } + + setSymptomsDate(date: string) { + cy.get("#symptoms_onset_date") + .click() + .then(() => { + cy.get("[placeholder='DD/MM/YYYY']").type(date); + }); + } + + updateConsultation() { + cy.intercept("PUT", "**/api/v1/consultation/**").as("updateConsultation"); + cy.get("#submit").contains("Update Consultation").click(); + cy.wait("@updateConsultation").its("response.statusCode").should("eq", 200); + } + + verifySuccessNotification(message: string) { + cy.verifyNotification(message); + } + + updateSymptoms(symptoms: string) { + this.selectSymptoms(symptoms); + cy.get("#symptoms").click(); + } + + visitShiftRequestPage() { + cy.get("#create_shift_request").click(); + } + + enterPatientShiftDetails( + name: string, + phone_number: string, + facilityName: string, + reason: string + ) { + cy.get("#refering_facility_contact_name").type(name); + cy.get("#refering_facility_contact_number").type(phone_number); + cy.get("input[name='assigned_facility']") + .type(facilityName) + .then(() => { + cy.get("[role='option']").first().click(); + }); + cy.get("#reason").type(reason); + } + + createShiftRequest() { + cy.intercept("POST", "**/api/v1/shift/").as("createShiftRequest"); + cy.get("#submit").click(); + cy.wait("@createShiftRequest").its("response.statusCode").should("eq", 201); + } + + visitDoctorNotesPage() { + cy.get("#patient_doctor_notes").click(); + } + + addDoctorsNotes(notes: string) { + cy.get("#doctor_notes_textarea").type(notes); + } + + postDoctorNotes() { + cy.intercept("POST", "**/api/v1/patient/*/notes").as("postDoctorNotes"); + cy.get("#submit").contains("Post Your Note").click(); + cy.wait("@postDoctorNotes").its("response.statusCode").should("eq", 201); + } + + clickDischargePatient() { + cy.get("#discharge_patient_from_care").click(); + } + + selectDischargeReason(reason: string) { + cy.get("#discharge_reason") + .click() + .then(() => { + cy.get("[role='option']").contains(reason).click(); + }); + } + + addDischargeNotes(notes: string) { + cy.get("#discharge_notes").type(notes); + } + + confirmDischarge() { + cy.intercept("POST", "**/api/v1/consultation/*/discharge_patient/").as( + "dischargePatient" + ); + cy.get("#submit").contains("Confirm Discharge").click(); + cy.wait("@dischargePatient").its("response.statusCode").should("eq", 200); + } + + discontinuePreviousPrescription() { + cy.intercept( + "POST", + "**/api/v1/consultation/*/prescriptions/*/discontinue/" + ).as("deletePrescription"); + cy.get("button").contains("Discontinue").click(); + cy.get("#submit").contains("Discontinue").click(); + cy.wait("@deletePrescription").its("response.statusCode").should("eq", 200); + } + + visitEditPrescriptionPage() { + cy.get("#consultation_tab_nav").contains("Medicines").click(); + cy.get("a[href='prescriptions']").first().click(); + } + + submitPrescription() { + cy.intercept("POST", "**/api/v1/consultation/*/prescriptions/").as( + "submitPrescription" + ); + cy.get("#submit").contains("Submit").click(); + cy.wait("@submitPrescription").its("response.statusCode").should("eq", 201); + } } diff --git a/cypress/pageobject/Patient/PatientCreation.ts b/cypress/pageobject/Patient/PatientCreation.ts index 4fcd43dc490..47bf9c913ad 100644 --- a/cypress/pageobject/Patient/PatientCreation.ts +++ b/cypress/pageobject/Patient/PatientCreation.ts @@ -10,6 +10,12 @@ export class PatientPage { cy.wait("@getFacilities").its("response.statusCode").should("eq", 200); } + visitPatient() { + cy.intercept("GET", "**/api/v1/consultation/**").as("getPatient"); + cy.get("[data-cy='patient']").first().click(); + cy.wait("@getPatient").its("response.statusCode").should("eq", 200); + } + selectFacility(facilityName: string) { cy.get("input[name='facilities']") .type(facilityName) diff --git a/cypress/pageobject/Users/UserCreation.ts b/cypress/pageobject/Users/UserCreation.ts new file mode 100644 index 00000000000..6bef3584ec8 --- /dev/null +++ b/cypress/pageobject/Users/UserCreation.ts @@ -0,0 +1,65 @@ +// UserCreation.ts +export class UserCreationPage { + clickElementById(elementId: string) { + cy.get("#" + elementId).click(); + } + + typeIntoElementById(elementId: string, value: string) { + cy.get("#" + elementId) + .click() + .type(value); + } + + typeIntoInputByName(inputName: string, value: string) { + cy.get("input[name='" + inputName + "']") + .click() + .type(value); + } + + selectOptionContainingText(text: string) { + cy.get("[role='option']").contains(text).click(); + } + + verifyNotification(message: string) { + cy.verifyNotification(message); + } + + selectFacility(name: string) { + this.typeIntoInputByName("facilities", name); + this.selectOptionContainingText(name); + } + + selectHomeFacility(name: string) { + this.clickElementById("home_facility"); + this.selectOptionContainingText(name); + } + + setInputDate( + dateElementId: string, + inputElementId: string, + dateValue: string + ) { + this.clickElementById(dateElementId); + this.typeIntoElementById(inputElementId, dateValue); + } + + selectDropdownOption(dropdownId: string, optionText: string) { + this.clickElementById(dropdownId); + this.selectOptionContainingText(optionText); + } + + verifyElementContainsText(elementId: string, expectedText: string) { + cy.get("#" + elementId).should("contain.text", expectedText); + } + + verifyErrorMessages(errorMessages: string[]) { + cy.get(".error-text").then(($errors) => { + const displayedErrorMessages = $errors + .map((_, el) => Cypress.$(el).text()) + .get(); + errorMessages.forEach((errorMessage) => { + expect(displayedErrorMessages).to.include(errorMessage); + }); + }); + } +} diff --git a/cypress/pageobject/Users/UserSearch.ts b/cypress/pageobject/Users/UserSearch.ts new file mode 100644 index 00000000000..4956532277f --- /dev/null +++ b/cypress/pageobject/Users/UserSearch.ts @@ -0,0 +1,112 @@ +// UserPage.ts +export class UserPage { + // Element selectors + searchByUsernameInput = "#search-by-username"; + usernameText = "#username"; + usernameBadge = "[data-testid='Username']"; + removeIcon = "#removeicon"; + + checkSearchInputVisibility() { + cy.get(this.searchByUsernameInput).should("be.visible"); + } + + typeInSearchInput(text: string) { + cy.get(this.searchByUsernameInput).click().type(text); + } + + clearSearchInput() { + cy.get(this.searchByUsernameInput).click().clear(); + } + + checkUrlForUsername(username: string) { + cy.url().should("include", `username=${username}`); + } + + verifyUrlafteradvancefilter() { + cy.url() + .should("include", "first_name=Dev") + .and("include", "last_name=Doctor") + .and("include", "phone_number=%2B919876543219") + .and("include", "alt_phone_number=%2B919876543219") + .and("include", "user_type=Doctor") + .and("include", "district_id=7"); + } + + checkUsernameText(username: string) { + cy.get(this.usernameText).should("have.text", username); + } + + checkUsernameBadgeVisibility(shouldBeVisible: boolean) { + const assertion = shouldBeVisible ? "be.visible" : "not.be.visible"; + cy.get(this.usernameBadge).should(assertion); + } + + clickRemoveIcon() { + cy.get(this.removeIcon).click(); + } + + clickAdvancedFilters() { + cy.get("#advanced-filter").contains("Advanced Filters").click(); + } + + typeInFirstName(firstName: string) { + cy.get("#first_name").click().type(firstName); + } + + typeInLastName(lastName: string) { + cy.get("#last_name").click().type(lastName); + } + + selectRole(role: string) { + cy.get("#role button").click(); + cy.get("[role='option']").contains(role).click(); + } + + selectDistrict(district: string) { + cy.get("input[name='district']").click().type(district); + cy.get("[role='option']").contains(district).click(); + } + + typeInPhoneNumber(phone: string) { + cy.get("#phone_number").click().type(phone); + } + + typeInAltPhoneNumber(altPhone: string) { + cy.get("#alt_phone_number").click().type(altPhone); + } + + applyFilter() { + cy.get("#apply-filter").click(); + } + + verifyDataTestIdText(testId: string, text: string) { + cy.get(`[data-testid="${testId}"]`).contains(text).should("be.visible"); + } + + clearFilters() { + this.clickAdvancedFilters(); + cy.get("#clear-filter").contains("Clear").click(); + } + + verifyDataTestIdNotVisible(testId: string) { + cy.get(`[data-testid="${testId}"]`).should("not.be.visible"); + } + + navigateToNextPage() { + cy.get("button#next-pages").click(); + } + + navigateToPreviousPage() { + cy.get("button#prev-pages").click(); + } + + verifyCurrentPageNumber(pageNumber: number) { + cy.url().should("include", `page=${pageNumber}`); + } + + verifyMultipleBadgesWithSameId(expectedContents: string[]) { + cy.get("#user-view-name").each((el, index) => { + expect(el.text().trim()).to.equal(expectedContents[index]); + }); + } +} diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 7f5484564fc..2dd8c477233 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -81,7 +81,7 @@ Cypress.Commands.add( Cypress.Commands.add("verifyNotification", (text) => { cy.get(".pnotify-container").should("exist").contains(text); - return cy.get(".pnotify-container").click({ force: true }); + return cy.get(".pnotify-container").contains(text).click({ force: true }); }); Cypress.on("uncaught:exception", () => { diff --git a/package-lock.json b/package-lock.json index 2a9fe3f520f..29d2abb713f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,10 +29,11 @@ "dayjs": "^1.11.9", "echarts": "^5.4.2", "echarts-for-react": "^3.0.2", + "eslint-mdx": "^2.2.0", "events": "^3.3.0", "i18next": "^23.2.7", "i18next-browser-languagedetector": "^7.1.0", - "lodash": "^4.17.21", + "lodash-es": "^4.17.21", "postcss-loader": "^7.3.3", "qrcode.react": "^3.1.0", "raviger": "^4.1.2", @@ -46,7 +47,7 @@ "react-google-recaptcha": "^3.1.0", "react-i18next": "^13.0.1", "react-markdown": "^8.0.7", - "react-player": "^2.12.0", + "react-player": "^2.13.0", "react-qr-reader": "^2.2.1", "react-redux": "^8.1.1", "react-transition-group": "^4.4.5", @@ -57,7 +58,7 @@ "rehype-raw": "^6.1.1", "rescript-webapi": "^0.8.0", "use-keyboard-shortcut": "^1.1.6", - "uuid": "^9.0.0" + "uuid": "^9.0.1" }, "devDependencies": { "@storybook/addon-essentials": "^7.0.26", @@ -73,7 +74,7 @@ "@types/cypress": "^1.1.3", "@types/echarts": "^4.9.18", "@types/google.maps": "^3.53.4", - "@types/lodash": "^4.14.195", + "@types/lodash-es": "^4.17.9", "@types/lodash.get": "^4.4.7", "@types/node": "^20.4.0", "@types/prop-types": "*", @@ -97,6 +98,7 @@ "eslint-plugin-i18next": "^6.0.3", "eslint-plugin-import": "^2.27.5", "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-mdx": "^2.2.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-only-warn": "^1.1.0", "eslint-plugin-prettier": "^4.2.1", @@ -3234,7 +3236,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -3247,7 +3248,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "engines": { "node": ">= 8" } @@ -3256,7 +3256,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -3265,6 +3264,106 @@ "node": ">= 8" } }, + "node_modules/@npmcli/config": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@npmcli/config/-/config-6.4.0.tgz", + "integrity": "sha512-/fQjIbuNVIT/PbXvw178Tm97bxV0E0nVUFKHivMKtSI2pcs8xKdaWkHJxf9dTI0G/y5hp/KuCvgcUu5HwAtI1w==", + "dependencies": { + "@npmcli/map-workspaces": "^3.0.2", + "ci-info": "^3.8.0", + "ini": "^4.1.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/config/node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/config/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/config/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/config/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@npmcli/map-workspaces": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-3.0.4.tgz", + "integrity": "sha512-Z0TbvXkRbacjFFLpVpV0e2mheCh+WzQpcqL+4xp49uNJOxOnIAPZyXtUxZ5Qn3QBTGKA11Exjd9a5411rBrhDg==", + "dependencies": { + "@npmcli/name-from-folder": "^2.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0", + "read-package-json-fast": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/map-workspaces/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/name-from-folder": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz", + "integrity": "sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -3274,6 +3373,53 @@ "node": ">=14" } }, + "node_modules/@pkgr/utils": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", + "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", + "dependencies": { + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.0", + "is-glob": "^4.0.3", + "open": "^9.1.0", + "picocolors": "^1.0.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@pkgr/utils/node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@pkgr/utils/node_modules/open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dependencies": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@pnotify/core": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@pnotify/core/-/core-5.2.0.tgz", @@ -5235,6 +5381,14 @@ "@testing-library/dom": ">=7.21.4" } }, + "node_modules/@types/acorn": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", + "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/@types/aria-query": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", @@ -5287,6 +5441,14 @@ "@types/node": "*" } }, + "node_modules/@types/concat-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-2.0.1.tgz", + "integrity": "sha512-v5HP9ZsRbzFq5XRo2liUZPKzwbGK5SuGVMWZjE6iJOm/JNdESk3/rkfcPe0lcal0C32PTLVlYUYqGpMGNdDsDg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -5364,8 +5526,15 @@ "node_modules/@types/estree": { "version": "0.0.51", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.2.tgz", + "integrity": "sha512-GNBWlGBMjiiiL5TSkvPtOteuXsiVitw5MYGY1UYlrAq0SKyczsls6sCD7TZ8fsjRsvCVxml7EbyjJezPb3DrSA==", + "dependencies": { + "@types/estree": "*" + } }, "node_modules/@types/express": { "version": "4.17.17", @@ -5441,6 +5610,11 @@ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" }, + "node_modules/@types/is-empty": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/is-empty/-/is-empty-1.2.2.tgz", + "integrity": "sha512-BmFyKRHSsE+LFmOUQIYMg/8UJ+fNX3fxev0/OXGKWxUldHD8/bQYhXsTF7wR8woS0h8CWdLK39REjQ/Fxm6bFg==" + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", @@ -5483,6 +5657,15 @@ "integrity": "sha512-22y3o88f4a94mKljsZcanlNWPzO0uBsBdzLAngf2tp533LzZcQzb6+eZPJ+vCTt+bqF2XnvT9gejTLsAcJAJyQ==", "dev": true }, + "node_modules/@types/lodash-es": { + "version": "4.17.9", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.9.tgz", + "integrity": "sha512-ZTcmhiI3NNU7dEvWLZJkzG6ao49zOIjEgIE0RgV7wbPxU0f2xT3VSAHw2gmst8swH6V0YkLRGp4qPlX/6I90MQ==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/lodash.get": { "version": "4.4.7", "resolved": "https://registry.npmjs.org/@types/lodash.get/-/lodash.get-4.4.7.tgz", @@ -5697,6 +5880,11 @@ "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", "dev": true }, + "node_modules/@types/supports-color": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.2.tgz", + "integrity": "sha512-nhs1D8NjNueBqRBhBTsc81g90g7VBD4wnMTMy9oP+QIldHuJkE655QTL2D1jkj3LyCd+Q5Y69oOpfxN1l0eCMA==" + }, "node_modules/@types/trusted-types": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", @@ -6140,6 +6328,14 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -6168,7 +6364,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -6884,7 +7079,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, "dependencies": { "big-integer": "^1.6.44" }, @@ -7011,8 +7205,7 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/buffer-indexof-polyfill": { "version": "1.0.2", @@ -7042,6 +7235,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dependencies": { + "run-applescript": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -7162,6 +7369,15 @@ "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chainsaw": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", @@ -7197,6 +7413,33 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/check-more-types": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", @@ -7256,7 +7499,6 @@ "version": "3.8.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, "funding": [ { "type": "github", @@ -8038,11 +8280,27 @@ "node": ">=0.10.0" } }, + "node_modules/default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/default-browser-id": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, "dependencies": { "bplist-parser": "^0.2.0", "untildify": "^4.0.0" @@ -8054,43 +8312,156 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "node_modules/default-browser/node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", "dependencies": { - "clone": "^1.0.2" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/default-browser/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, + "node_modules/default-browser/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", "engines": { - "node": ">=8" + "node": ">=14.18.0" } }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "node_modules/default-browser/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/defu": { - "version": "6.1.2", + "node_modules/default-browser/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defu": { + "version": "6.1.2", "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.2.tgz", "integrity": "sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==", "dev": true @@ -8877,6 +9248,48 @@ "ms": "^2.1.1" } }, + "node_modules/eslint-mdx": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-mdx/-/eslint-mdx-2.2.0.tgz", + "integrity": "sha512-AriN6lCW6KhWQ9GEiXapR1DokKHefOUqKvCmHxnE9puCWYhWiycU2SNKH8jmrasDBreZ+RtJDLi+RcUNLJatjg==", + "dependencies": { + "acorn": "^8.10.0", + "acorn-jsx": "^5.3.2", + "espree": "^9.6.1", + "estree-util-visit": "^1.2.1", + "remark-mdx": "^2.3.0", + "remark-parse": "^10.0.2", + "remark-stringify": "^10.0.3", + "synckit": "^0.8.5", + "tslib": "^2.6.1", + "unified": "^10.1.2", + "unified-engine": "^10.1.0", + "unist-util-visit": "^4.1.2", + "uvu": "^0.5.6", + "vfile": "^5.3.7" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "eslint": ">=8.0.0" + } + }, + "node_modules/eslint-mdx/node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/eslint-module-utils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", @@ -9015,6 +9428,199 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, + "node_modules/eslint-plugin-markdown": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-3.0.1.tgz", + "integrity": "sha512-8rqoc148DWdGdmYF6WSQFT3uQ6PO7zXYgeBpHAOAakX/zpq+NvFYbDA/H7PYzHajwtmaOzAwfxyl++x0g1/N9A==", + "dev": true, + "dependencies": { + "mdast-util-from-markdown": "^0.8.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-markdown/node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/eslint-plugin-markdown/node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/eslint-plugin-markdown/node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/eslint-plugin-markdown/node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/eslint-plugin-markdown/node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "dev": true, + "dependencies": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/eslint-plugin-markdown/node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/eslint-plugin-markdown/node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/eslint-plugin-markdown/node_modules/mdast-util-from-markdown": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz", + "integrity": "sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-string": "^2.0.0", + "micromark": "~2.11.0", + "parse-entities": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/eslint-plugin-markdown/node_modules/mdast-util-to-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", + "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/eslint-plugin-markdown/node_modules/micromark": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz", + "integrity": "sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "debug": "^4.0.0", + "parse-entities": "^2.0.0" + } + }, + "node_modules/eslint-plugin-markdown/node_modules/parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "dev": true, + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/eslint-plugin-markdown/node_modules/unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/eslint-plugin-mdx": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mdx/-/eslint-plugin-mdx-2.2.0.tgz", + "integrity": "sha512-OseoMXUIr8iy3E0me+wJLVAxuB0kxHP1plxuYAJDynzorzOj2OKv8Fhr+rIOJ32zfl3bnEWsqFnUiCnyznr1JQ==", + "dev": true, + "dependencies": { + "eslint-mdx": "^2.2.0", + "eslint-plugin-markdown": "^3.0.1", + "remark-mdx": "^2.3.0", + "remark-parse": "^10.0.2", + "remark-stringify": "^10.0.3", + "tslib": "^2.6.1", + "unified": "^10.1.2", + "vfile": "^5.3.7" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "eslint": ">=8.0.0" + } + }, "node_modules/eslint-plugin-node": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", @@ -9213,7 +9819,6 @@ "version": "3.4.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -9286,7 +9891,6 @@ "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -9303,7 +9907,6 @@ "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -9370,6 +9973,28 @@ "node": ">=8.3.0" } }, + "node_modules/estree-util-is-identifier-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.1.0.tgz", + "integrity": "sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-visit": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-1.2.1.tgz", + "integrity": "sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", @@ -9559,7 +10184,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -9575,7 +10199,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -9599,11 +10222,22 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, "dependencies": { "reusify": "^1.0.4" } }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -9942,6 +10576,14 @@ "node": ">= 6" } }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -10877,7 +11519,6 @@ "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, "engines": { "node": ">= 4" } @@ -10905,6 +11546,15 @@ "node": ">=4" } }, + "node_modules/import-meta-resolve": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-2.2.2.tgz", + "integrity": "sha512-f8KcQ1D80V7RnqVm+/lirO9zkOxjGxhaTC1IPrBGd3MEfNgmNG67tSUO9gTi2F3Blr2Az6g1vocaxzkVnWl9MA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -10996,6 +11646,28 @@ "node": ">=8" } }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -11141,6 +11813,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-deflate": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", @@ -11151,7 +11832,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, "bin": { "is-docker": "cli.js" }, @@ -11162,6 +11842,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-empty": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz", + "integrity": "sha512-F2FnH/otLNJv0J6wc73A5Xo7oHLNnqplYqZhUu01tD54DIPvxIRSTSLkrUB/M0nHO4vo1O9PDfN4KoTxCzLh/w==" + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -11216,6 +11901,46 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -11403,7 +12128,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -11511,7 +12235,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -12420,6 +13143,19 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/load-plugin": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/load-plugin/-/load-plugin-5.1.0.tgz", + "integrity": "sha512-Lg1CZa1CFj2CbNaxijTL6PCbzd4qGTlZov+iH2p5Xwy/ApcZJh+i6jMN2cYePouTfjJfrNu3nXFdEw8LvbjPFQ==", + "dependencies": { + "@npmcli/config": "^6.0.0", + "import-meta-resolve": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/load-script": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", @@ -12454,6 +13190,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.castarray": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", @@ -12569,6 +13310,15 @@ "node": ">=8" } }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -12738,6 +13488,90 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-mdx": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-2.0.1.tgz", + "integrity": "sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==", + "dependencies": { + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-mdx-expression": "^1.0.0", + "mdast-util-mdx-jsx": "^2.0.0", + "mdast-util-mdxjs-esm": "^1.0.0", + "mdast-util-to-markdown": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.2.tgz", + "integrity": "sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-to-markdown": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-2.1.4.tgz", + "integrity": "sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "ccount": "^2.0.0", + "mdast-util-from-markdown": "^1.1.0", + "mdast-util-to-markdown": "^1.3.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-remove-position": "^4.0.0", + "unist-util-stringify-position": "^3.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-1.3.1.tgz", + "integrity": "sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-to-markdown": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==", + "dependencies": { + "@types/mdast": "^3.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-to-hast": { "version": "12.3.0", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz", @@ -12771,6 +13605,25 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-to-markdown": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz", + "integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==", + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^3.0.0", + "mdast-util-to-string": "^3.0.0", + "micromark-util-decode-string": "^1.0.0", + "unist-util-visit": "^4.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-to-string": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", @@ -12812,14 +13665,12 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "engines": { "node": ">= 8" } @@ -12899,6 +13750,129 @@ "uvu": "^0.5.0" } }, + "node_modules/micromark-extension-mdx-expression": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-1.0.8.tgz", + "integrity": "sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "micromark-factory-mdx-expression": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-events-to-acorn": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/@types/estree": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", + "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==" + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-1.0.5.tgz", + "integrity": "sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA==", + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "estree-util-is-identifier-name": "^2.0.0", + "micromark-factory-mdx-expression": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/@types/estree": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", + "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==" + }, + "node_modules/micromark-extension-mdx-md": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-1.0.1.tgz", + "integrity": "sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA==", + "dependencies": { + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-1.0.1.tgz", + "integrity": "sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^1.0.0", + "micromark-extension-mdx-jsx": "^1.0.0", + "micromark-extension-mdx-md": "^1.0.0", + "micromark-extension-mdxjs-esm": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-1.0.5.tgz", + "integrity": "sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w==", + "dependencies": { + "@types/estree": "^1.0.0", + "micromark-core-commonmark": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-events-to-acorn": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "unist-util-position-from-estree": "^1.1.0", + "uvu": "^0.5.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/@types/estree": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", + "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==" + }, + "node_modules/micromark-extension-mdxjs/node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/micromark-factory-destination": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", @@ -12940,6 +13914,36 @@ "uvu": "^0.5.0" } }, + "node_modules/micromark-factory-mdx-expression": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-1.0.9.tgz", + "integrity": "sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-events-to-acorn": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "unist-util-position-from-estree": "^1.0.0", + "uvu": "^0.5.0", + "vfile-message": "^3.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/@types/estree": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", + "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==" + }, "node_modules/micromark-factory-space": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", @@ -13131,6 +14135,36 @@ } ] }, + "node_modules/micromark-util-events-to-acorn": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-1.2.3.tgz", + "integrity": "sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "@types/unist": "^2.0.0", + "estree-util-visit": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0", + "vfile-message": "^3.0.0" + } + }, + "node_modules/micromark-util-events-to-acorn/node_modules/@types/estree": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", + "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==" + }, "node_modules/micromark-util-html-tag-name": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", @@ -13257,7 +14291,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -13300,7 +14333,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -13515,6 +14547,20 @@ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "dev": true }, + "node_modules/nopt": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -13706,11 +14752,18 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -13720,6 +14773,8 @@ }, "node_modules/npm/node_modules/@colors/colors": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -13730,6 +14785,8 @@ }, "node_modules/npm/node_modules/@isaacs/cliui": { "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "inBundle": true, "license": "ISC", @@ -13747,6 +14804,8 @@ }, "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, "inBundle": true, "license": "MIT", @@ -13759,6 +14818,8 @@ }, "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, "inBundle": true, "license": "MIT" @@ -13782,6 +14843,8 @@ }, "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -13797,6 +14860,8 @@ }, "node_modules/npm/node_modules/@isaacs/string-locale-compare": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", + "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==", "dev": true, "inBundle": true, "license": "ISC" @@ -13869,6 +14934,8 @@ }, "node_modules/npm/node_modules/@npmcli/disparity-colors": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/disparity-colors/-/disparity-colors-3.0.0.tgz", + "integrity": "sha512-5R/z157/f20Fi0Ou4ZttL51V0xz0EdPEOauFtPCEYOLInDBRCj1/TxOJ5aGTrtShxEshN2d+hXb9ZKSi5RLBcg==", "dev": true, "inBundle": true, "license": "ISC", @@ -13881,6 +14948,8 @@ }, "node_modules/npm/node_modules/@npmcli/fs": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", "dev": true, "inBundle": true, "license": "ISC", @@ -13893,6 +14962,8 @@ }, "node_modules/npm/node_modules/@npmcli/git": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", + "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -13912,6 +14983,8 @@ }, "node_modules/npm/node_modules/@npmcli/installed-package-contents": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", + "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -13928,6 +15001,8 @@ }, "node_modules/npm/node_modules/@npmcli/map-workspaces": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-3.0.4.tgz", + "integrity": "sha512-Z0TbvXkRbacjFFLpVpV0e2mheCh+WzQpcqL+4xp49uNJOxOnIAPZyXtUxZ5Qn3QBTGKA11Exjd9a5411rBrhDg==", "dev": true, "inBundle": true, "license": "ISC", @@ -13943,6 +15018,8 @@ }, "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-5.0.1.tgz", + "integrity": "sha512-qb8Q9wIIlEPj3WeA1Lba91R4ZboPL0uspzV0F9uwP+9AYMVB2zOoa7Pbk12g6D2NHAinSbHh6QYmGuRyHZ874Q==", "dev": true, "inBundle": true, "license": "ISC", @@ -13958,6 +15035,8 @@ }, "node_modules/npm/node_modules/@npmcli/name-from-folder": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz", + "integrity": "sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==", "dev": true, "inBundle": true, "license": "ISC", @@ -13967,6 +15046,8 @@ }, "node_modules/npm/node_modules/@npmcli/node-gyp": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", + "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", "dev": true, "inBundle": true, "license": "ISC", @@ -13976,6 +15057,8 @@ }, "node_modules/npm/node_modules/@npmcli/package-json": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha512-lRCEGdHZomFsURroh522YvA/2cVb9oPIJrjHanCJZkiasz1BzcnLr3tBJhlV7S86MBJBuAQ33is2D60YitZL2Q==", "dev": true, "inBundle": true, "license": "ISC", @@ -13994,6 +15077,8 @@ }, "node_modules/npm/node_modules/@npmcli/promise-spawn": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", + "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", "dev": true, "inBundle": true, "license": "ISC", @@ -14018,6 +15103,8 @@ }, "node_modules/npm/node_modules/@npmcli/run-script": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", + "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", "dev": true, "inBundle": true, "license": "ISC", @@ -14034,6 +15121,8 @@ }, "node_modules/npm/node_modules/@pkgjs/parseargs": { "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "inBundle": true, "license": "MIT", @@ -14066,6 +15155,8 @@ }, "node_modules/npm/node_modules/@tootallnate/once": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, "inBundle": true, "license": "MIT", @@ -14075,6 +15166,8 @@ }, "node_modules/npm/node_modules/@tufjs/canonical-json": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", + "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -14084,6 +15177,8 @@ }, "node_modules/npm/node_modules/@tufjs/models": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz", + "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==", "dev": true, "inBundle": true, "license": "MIT", @@ -14097,6 +15192,8 @@ }, "node_modules/npm/node_modules/abbrev": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -14106,6 +15203,8 @@ }, "node_modules/npm/node_modules/abort-controller": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "dev": true, "inBundle": true, "license": "MIT", @@ -14118,6 +15217,8 @@ }, "node_modules/npm/node_modules/agent-base": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -14144,6 +15245,8 @@ }, "node_modules/npm/node_modules/aggregate-error": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "inBundle": true, "license": "MIT", @@ -14157,6 +15260,8 @@ }, "node_modules/npm/node_modules/ansi-regex": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -14166,6 +15271,8 @@ }, "node_modules/npm/node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "inBundle": true, "license": "MIT", @@ -14181,12 +15288,16 @@ }, "node_modules/npm/node_modules/aproba": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/archy": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true, "inBundle": true, "license": "MIT" @@ -14206,12 +15317,16 @@ }, "node_modules/npm/node_modules/balanced-match": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/base64-js": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, "funding": [ { @@ -14247,6 +15362,8 @@ }, "node_modules/npm/node_modules/binary-extensions": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, "inBundle": true, "license": "MIT", @@ -14256,6 +15373,8 @@ }, "node_modules/npm/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "inBundle": true, "license": "MIT", @@ -14265,6 +15384,8 @@ }, "node_modules/npm/node_modules/buffer": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, "funding": [ { @@ -14289,6 +15410,8 @@ }, "node_modules/npm/node_modules/builtins": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -14321,6 +15444,8 @@ }, "node_modules/npm/node_modules/chalk": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, "inBundle": true, "license": "MIT", @@ -14333,6 +15458,8 @@ }, "node_modules/npm/node_modules/chownr": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -14342,6 +15469,8 @@ }, "node_modules/npm/node_modules/ci-info": { "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true, "funding": [ { @@ -14357,6 +15486,8 @@ }, "node_modules/npm/node_modules/cidr-regex": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/cidr-regex/-/cidr-regex-3.1.1.tgz", + "integrity": "sha512-RBqYd32aDwbCMFJRL6wHOlDNYJsPNTt8vC82ErHF5vKt8QQzxm1FrkW8s/R5pVrXMf17sba09Uoy91PKiddAsw==", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -14369,6 +15500,8 @@ }, "node_modules/npm/node_modules/clean-stack": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, "inBundle": true, "license": "MIT", @@ -14378,6 +15511,8 @@ }, "node_modules/npm/node_modules/cli-columns": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-columns/-/cli-columns-4.0.0.tgz", + "integrity": "sha512-XW2Vg+w+L9on9wtwKpyzluIPCWXjaBahI7mTcYjx+BVIYD9c3yqcv/yKC7CmdCZat4rq2yiE1UMSJC5ivKfMtQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -14391,6 +15526,8 @@ }, "node_modules/npm/node_modules/cli-table3": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", "dev": true, "inBundle": true, "license": "MIT", @@ -14406,6 +15543,8 @@ }, "node_modules/npm/node_modules/clone": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, "inBundle": true, "license": "MIT", @@ -14415,6 +15554,8 @@ }, "node_modules/npm/node_modules/cmd-shim": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-6.0.1.tgz", + "integrity": "sha512-S9iI9y0nKR4hwEQsVWpyxld/6kRfGepGfzff83FcaiEBpmvlbA2nnGe7Cylgrx2f/p1P5S5wpRm9oL8z1PbS3Q==", "dev": true, "inBundle": true, "license": "ISC", @@ -14424,6 +15565,8 @@ }, "node_modules/npm/node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -14436,12 +15579,16 @@ }, "node_modules/npm/node_modules/color-name": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/color-support": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true, "inBundle": true, "license": "ISC", @@ -14451,6 +15598,8 @@ }, "node_modules/npm/node_modules/columnify": { "version": "1.6.0", + "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", + "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", "dev": true, "inBundle": true, "license": "MIT", @@ -14464,24 +15613,32 @@ }, "node_modules/npm/node_modules/common-ancestor-path": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/concat-map": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/console-control-strings": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/cross-spawn": { "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "inBundle": true, "license": "MIT", @@ -14511,6 +15668,8 @@ }, "node_modules/npm/node_modules/cssesc": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, "inBundle": true, "license": "MIT", @@ -14523,6 +15682,8 @@ }, "node_modules/npm/node_modules/debug": { "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -14546,6 +15707,8 @@ }, "node_modules/npm/node_modules/defaults": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, "inBundle": true, "license": "MIT", @@ -14558,6 +15721,8 @@ }, "node_modules/npm/node_modules/delegates": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true, "inBundle": true, "license": "MIT" @@ -14573,6 +15738,8 @@ }, "node_modules/npm/node_modules/diff": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", "dev": true, "inBundle": true, "license": "BSD-3-Clause", @@ -14582,18 +15749,24 @@ }, "node_modules/npm/node_modules/eastasianwidth": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/encoding": { "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, "inBundle": true, "license": "MIT", @@ -14604,6 +15777,8 @@ }, "node_modules/npm/node_modules/env-paths": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, "inBundle": true, "license": "MIT", @@ -14613,12 +15788,16 @@ }, "node_modules/npm/node_modules/err-code": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/event-target-shim": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -14628,6 +15807,8 @@ }, "node_modules/npm/node_modules/events": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, "inBundle": true, "license": "MIT", @@ -14637,12 +15818,16 @@ }, "node_modules/npm/node_modules/exponential-backoff": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", "dev": true, "inBundle": true, "license": "Apache-2.0" }, "node_modules/npm/node_modules/fastest-levenshtein": { "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, "inBundle": true, "license": "MIT", @@ -14652,6 +15837,8 @@ }, "node_modules/npm/node_modules/foreground-child": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", "dev": true, "inBundle": true, "license": "ISC", @@ -14680,18 +15867,24 @@ }, "node_modules/npm/node_modules/fs.realpath": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/function-bind": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/gauge": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-5.0.1.tgz", + "integrity": "sha512-CmykPMJGuNan/3S4kZOpvvPYSNqSHANiWnh9XcMU2pSjtBfF0XzZ2p1bFAxTbnFxyBuPxQYHhzwaoOmUdqzvxQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -14733,12 +15926,16 @@ }, "node_modules/npm/node_modules/graceful-fs": { "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/has": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "inBundle": true, "license": "MIT", @@ -14751,12 +15948,16 @@ }, "node_modules/npm/node_modules/has-unicode": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/hosted-git-info": { "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", "dev": true, "inBundle": true, "license": "ISC", @@ -14769,12 +15970,16 @@ }, "node_modules/npm/node_modules/http-cache-semantics": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true, "inBundle": true, "license": "BSD-2-Clause" }, "node_modules/npm/node_modules/http-proxy-agent": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, "inBundle": true, "license": "MIT", @@ -14789,6 +15994,8 @@ }, "node_modules/npm/node_modules/https-proxy-agent": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "inBundle": true, "license": "MIT", @@ -14802,6 +16009,8 @@ }, "node_modules/npm/node_modules/humanize-ms": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -14811,6 +16020,8 @@ }, "node_modules/npm/node_modules/iconv-lite": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "inBundle": true, "license": "MIT", @@ -14824,6 +16035,8 @@ }, "node_modules/npm/node_modules/ieee754": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, "funding": [ { @@ -14844,6 +16057,8 @@ }, "node_modules/npm/node_modules/ignore-walk": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz", + "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==", "dev": true, "inBundle": true, "license": "ISC", @@ -14856,6 +16071,8 @@ }, "node_modules/npm/node_modules/imurmurhash": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "inBundle": true, "license": "MIT", @@ -14865,6 +16082,8 @@ }, "node_modules/npm/node_modules/indent-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "inBundle": true, "license": "MIT", @@ -14874,6 +16093,8 @@ }, "node_modules/npm/node_modules/inflight": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "inBundle": true, "license": "ISC", @@ -14884,12 +16105,16 @@ }, "node_modules/npm/node_modules/inherits": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/ini": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", "dev": true, "inBundle": true, "license": "ISC", @@ -14899,6 +16124,8 @@ }, "node_modules/npm/node_modules/init-package-json": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-5.0.0.tgz", + "integrity": "sha512-kBhlSheBfYmq3e0L1ii+VKe3zBTLL5lDCDWR+f9dLmEGSB3MqLlMlsolubSsyI88Bg6EA+BIMlomAnQ1SwgQBw==", "dev": true, "inBundle": true, "license": "ISC", @@ -14917,12 +16144,16 @@ }, "node_modules/npm/node_modules/ip": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/ip-regex": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", "dev": true, "inBundle": true, "license": "MIT", @@ -14932,6 +16163,8 @@ }, "node_modules/npm/node_modules/is-cidr": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/is-cidr/-/is-cidr-4.0.2.tgz", + "integrity": "sha512-z4a1ENUajDbEl/Q6/pVBpTR1nBjjEE1X7qb7bmWYanNnPoKAvUCPFKeXV6Fe4mgTkWKBqiHIcwsI3SndiO5FeA==", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -14956,6 +16189,8 @@ }, "node_modules/npm/node_modules/is-fullwidth-code-point": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "inBundle": true, "license": "MIT", @@ -14965,12 +16200,16 @@ }, "node_modules/npm/node_modules/is-lambda": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/isexe": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "inBundle": true, "license": "ISC" @@ -14995,6 +16234,8 @@ }, "node_modules/npm/node_modules/json-parse-even-better-errors": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", "dev": true, "inBundle": true, "license": "MIT", @@ -15004,6 +16245,8 @@ }, "node_modules/npm/node_modules/json-stringify-nice": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", + "integrity": "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15013,6 +16256,8 @@ }, "node_modules/npm/node_modules/jsonparse": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "dev": true, "engines": [ "node >= 0.2.0" @@ -15022,18 +16267,24 @@ }, "node_modules/npm/node_modules/just-diff": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-6.0.2.tgz", + "integrity": "sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/just-diff-apply": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.5.0.tgz", + "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/libnpmaccess": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-7.0.2.tgz", + "integrity": "sha512-vHBVMw1JFMTgEk15zRsJuSAg7QtGGHpUSEfnbcRL1/gTBag9iEfJbyjpDmdJmwMhvpoLoNBtdAUCdGnaP32hhw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15101,6 +16352,8 @@ }, "node_modules/npm/node_modules/libnpmhook": { "version": "9.0.3", + "resolved": "https://registry.npmjs.org/libnpmhook/-/libnpmhook-9.0.3.tgz", + "integrity": "sha512-wMZe58sI7KLhg0+nUWZW5KdMfjNNcOIIbkoP19BDHYoUF9El7eeUWkGNxUGzpHkPKiGoQ1z/v6CYin4deebeuw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15114,6 +16367,8 @@ }, "node_modules/npm/node_modules/libnpmorg": { "version": "5.0.4", + "resolved": "https://registry.npmjs.org/libnpmorg/-/libnpmorg-5.0.4.tgz", + "integrity": "sha512-YqYXLMAN0Y1eJH4w3hUFN9648xfSdvJANMsdeZTOWJOW4Pqp8qapJFzQdqCfUkg+tEuQmnaFQQKXvkMZC51+Mw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15142,6 +16397,8 @@ }, "node_modules/npm/node_modules/libnpmpublish": { "version": "7.5.0", + "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-7.5.0.tgz", + "integrity": "sha512-zctH6QcTJ093lpxmkufr2zr3AJ9V90hcRilDFNin6n91ODj+S28RdyMFFJpa9NwyztmyV2hlWLyZv0GaOQBDyA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15161,6 +16418,8 @@ }, "node_modules/npm/node_modules/libnpmsearch": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/libnpmsearch/-/libnpmsearch-6.0.2.tgz", + "integrity": "sha512-p+5BF19AvnVg8mcIQhy6yWhI6jHQRVMYaIaKeITEfYAffWsqbottA/WZdMtHL76hViC6SFM1WdclM1w5eAIa1g==", "dev": true, "inBundle": true, "license": "ISC", @@ -15173,6 +16432,8 @@ }, "node_modules/npm/node_modules/libnpmteam": { "version": "5.0.3", + "resolved": "https://registry.npmjs.org/libnpmteam/-/libnpmteam-5.0.3.tgz", + "integrity": "sha512-7XOGhi45s+ml6TyrhJUTyrErcoDMKGKfEtiTEco4ofU7BGGAUOalVztKMVLLJgJOOXdIAIlzCHqkTXEuSiyCiA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15186,6 +16447,8 @@ }, "node_modules/npm/node_modules/libnpmversion": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/libnpmversion/-/libnpmversion-4.0.2.tgz", + "integrity": "sha512-n1X70mFHv8Piy4yos+MFWUARSkTbyV5cdsHScaIkuwYvRAF/s2VtYScDzWB4Oe8uNEuGNdjiRR1E/Dh1tMvv6g==", "dev": true, "inBundle": true, "license": "ISC", @@ -15202,6 +16465,8 @@ }, "node_modules/npm/node_modules/lru-cache": { "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15211,6 +16476,8 @@ }, "node_modules/npm/node_modules/make-fetch-happen": { "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", "dev": true, "inBundle": true, "license": "ISC", @@ -15237,6 +16504,8 @@ }, "node_modules/npm/node_modules/minimatch": { "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "inBundle": true, "license": "ISC", @@ -15261,6 +16530,8 @@ }, "node_modules/npm/node_modules/minipass-collect": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15302,6 +16573,8 @@ }, "node_modules/npm/node_modules/minipass-flush": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15326,6 +16599,8 @@ }, "node_modules/npm/node_modules/minipass-json-stream": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", "dev": true, "inBundle": true, "license": "MIT", @@ -15348,6 +16623,8 @@ }, "node_modules/npm/node_modules/minipass-pipeline": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, "inBundle": true, "license": "ISC", @@ -15372,6 +16649,8 @@ }, "node_modules/npm/node_modules/minipass-sized": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "dev": true, "inBundle": true, "license": "ISC", @@ -15396,6 +16675,8 @@ }, "node_modules/npm/node_modules/minizlib": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "inBundle": true, "license": "MIT", @@ -15421,6 +16702,8 @@ }, "node_modules/npm/node_modules/mkdirp": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "inBundle": true, "license": "MIT", @@ -15433,12 +16716,16 @@ }, "node_modules/npm/node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/mute-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15448,6 +16735,8 @@ }, "node_modules/npm/node_modules/negotiator": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "inBundle": true, "license": "MIT", @@ -15457,6 +16746,8 @@ }, "node_modules/npm/node_modules/node-gyp": { "version": "9.4.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", + "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", "dev": true, "inBundle": true, "license": "MIT", @@ -15482,12 +16773,16 @@ }, "node_modules/npm/node_modules/node-gyp/node_modules/abbrev": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/node-gyp/node_modules/are-we-there-yet": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", "dev": true, "inBundle": true, "license": "ISC", @@ -15501,6 +16796,8 @@ }, "node_modules/npm/node_modules/node-gyp/node_modules/brace-expansion": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "inBundle": true, "license": "MIT", @@ -15511,6 +16808,8 @@ }, "node_modules/npm/node_modules/node-gyp/node_modules/gauge": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", "dev": true, "inBundle": true, "license": "ISC", @@ -15550,6 +16849,8 @@ }, "node_modules/npm/node_modules/node-gyp/node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15592,6 +16893,8 @@ }, "node_modules/npm/node_modules/node-gyp/node_modules/readable-stream": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "inBundle": true, "license": "MIT", @@ -15606,6 +16909,8 @@ }, "node_modules/npm/node_modules/node-gyp/node_modules/signal-exit": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, "inBundle": true, "license": "ISC" @@ -15627,6 +16932,8 @@ }, "node_modules/npm/node_modules/nopt": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15642,6 +16949,8 @@ }, "node_modules/npm/node_modules/normalize-package-data": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", + "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -15657,6 +16966,8 @@ }, "node_modules/npm/node_modules/npm-audit-report": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-audit-report/-/npm-audit-report-5.0.0.tgz", + "integrity": "sha512-EkXrzat7zERmUhHaoren1YhTxFwsOu5jypE84k6632SXTHcQE1z8V51GC6GVZt8LxkC+tbBcKMUBZAgk8SUSbw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15666,6 +16977,8 @@ }, "node_modules/npm/node_modules/npm-bundled": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", + "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -15690,6 +17003,8 @@ }, "node_modules/npm/node_modules/npm-normalize-package-bin": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -15699,6 +17014,8 @@ }, "node_modules/npm/node_modules/npm-package-arg": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15714,6 +17031,8 @@ }, "node_modules/npm/node_modules/npm-packlist": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", + "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", "dev": true, "inBundle": true, "license": "ISC", @@ -15741,6 +17060,8 @@ }, "node_modules/npm/node_modules/npm-profile": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/npm-profile/-/npm-profile-7.0.1.tgz", + "integrity": "sha512-VReArOY/fCx5dWL66cbJ2OMogTQAVVQA//8jjmjkarboki3V7UJ0XbGFW+khRwiAJFQjuH0Bqr/yF7Y5RZdkMQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -15754,6 +17075,8 @@ }, "node_modules/npm/node_modules/npm-registry-fetch": { "version": "14.0.5", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz", + "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15772,6 +17095,8 @@ }, "node_modules/npm/node_modules/npm-user-validate": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/npm-user-validate/-/npm-user-validate-2.0.0.tgz", + "integrity": "sha512-sSWeqAYJ2dUPStJB+AEj0DyLRltr/f6YNcvCA7phkB8/RMLMnVsQ41GMwHo/ERZLYNDsyB2wPm7pZo1mqPOl7Q==", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -15781,6 +17106,8 @@ }, "node_modules/npm/node_modules/npmlog": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-7.0.1.tgz", + "integrity": "sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg==", "dev": true, "inBundle": true, "license": "ISC", @@ -15796,6 +17123,8 @@ }, "node_modules/npm/node_modules/once": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "inBundle": true, "license": "ISC", @@ -15805,6 +17134,8 @@ }, "node_modules/npm/node_modules/p-map": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -15820,6 +17151,8 @@ }, "node_modules/npm/node_modules/pacote": { "version": "15.2.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz", + "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15852,6 +17185,8 @@ }, "node_modules/npm/node_modules/parse-conflict-json": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-3.0.1.tgz", + "integrity": "sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15866,6 +17201,8 @@ }, "node_modules/npm/node_modules/path-is-absolute": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "inBundle": true, "license": "MIT", @@ -15875,6 +17212,8 @@ }, "node_modules/npm/node_modules/path-key": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "inBundle": true, "license": "MIT", @@ -15909,6 +17248,8 @@ }, "node_modules/npm/node_modules/postcss-selector-parser": { "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -15922,6 +17263,8 @@ }, "node_modules/npm/node_modules/proc-log": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", "dev": true, "inBundle": true, "license": "ISC", @@ -15931,6 +17274,8 @@ }, "node_modules/npm/node_modules/process": { "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", "dev": true, "inBundle": true, "license": "MIT", @@ -15940,6 +17285,8 @@ }, "node_modules/npm/node_modules/promise-all-reject-late": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", + "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15949,6 +17296,8 @@ }, "node_modules/npm/node_modules/promise-call-limit": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.2.tgz", + "integrity": "sha512-1vTUnfI2hzui8AEIixbdAJlFY4LFDXqQswy/2eOlThAscXCY4It8FdVuI0fMJGAB2aWGbdQf/gv0skKYXmdrHA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15958,12 +17307,16 @@ }, "node_modules/npm/node_modules/promise-inflight": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/promise-retry": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, "inBundle": true, "license": "MIT", @@ -15977,6 +17330,8 @@ }, "node_modules/npm/node_modules/promzard": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/promzard/-/promzard-1.0.0.tgz", + "integrity": "sha512-KQVDEubSUHGSt5xLakaToDFrSoZhStB8dXLzk2xvwR67gJktrHFvpR63oZgHyK19WKbHFLXJqCPXdVR3aBP8Ig==", "dev": true, "inBundle": true, "license": "ISC", @@ -15989,6 +17344,8 @@ }, "node_modules/npm/node_modules/qrcode-terminal": { "version": "0.12.0", + "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz", + "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==", "dev": true, "inBundle": true, "bin": { @@ -15997,6 +17354,8 @@ }, "node_modules/npm/node_modules/read": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/read/-/read-2.1.0.tgz", + "integrity": "sha512-bvxi1QLJHcaywCAEsAk4DG3nVoqiY2Csps3qzWalhj5hFqRn1d/OixkFXtLO1PrgHUcAP0FNaSY/5GYNfENFFQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -16009,6 +17368,8 @@ }, "node_modules/npm/node_modules/read-cmd-shim": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", + "integrity": "sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==", "dev": true, "inBundle": true, "license": "ISC", @@ -16018,6 +17379,8 @@ }, "node_modules/npm/node_modules/read-package-json": { "version": "6.0.4", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", + "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", "dev": true, "inBundle": true, "license": "ISC", @@ -16033,6 +17396,8 @@ }, "node_modules/npm/node_modules/read-package-json-fast": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", "dev": true, "inBundle": true, "license": "ISC", @@ -16061,6 +17426,8 @@ }, "node_modules/npm/node_modules/retry": { "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, "inBundle": true, "license": "MIT", @@ -16070,6 +17437,8 @@ }, "node_modules/npm/node_modules/rimraf": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "inBundle": true, "license": "ISC", @@ -16085,6 +17454,8 @@ }, "node_modules/npm/node_modules/rimraf/node_modules/brace-expansion": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "inBundle": true, "license": "MIT", @@ -16115,6 +17486,8 @@ }, "node_modules/npm/node_modules/rimraf/node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "inBundle": true, "license": "ISC", @@ -16127,6 +17500,8 @@ }, "node_modules/npm/node_modules/safe-buffer": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -16147,6 +17522,8 @@ }, "node_modules/npm/node_modules/safer-buffer": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "inBundle": true, "license": "MIT", @@ -16154,6 +17531,8 @@ }, "node_modules/npm/node_modules/semver": { "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "inBundle": true, "license": "ISC", @@ -16181,12 +17560,16 @@ }, "node_modules/npm/node_modules/set-blocking": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "inBundle": true, "license": "MIT", @@ -16199,6 +17582,8 @@ }, "node_modules/npm/node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "inBundle": true, "license": "MIT", @@ -16208,6 +17593,8 @@ }, "node_modules/npm/node_modules/signal-exit": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", "dev": true, "inBundle": true, "license": "ISC", @@ -16237,6 +17624,8 @@ }, "node_modules/npm/node_modules/smart-buffer": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, "inBundle": true, "license": "MIT", @@ -16247,6 +17636,8 @@ }, "node_modules/npm/node_modules/socks": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -16261,6 +17652,8 @@ }, "node_modules/npm/node_modules/socks-proxy-agent": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", "dev": true, "inBundle": true, "license": "MIT", @@ -16275,6 +17668,8 @@ }, "node_modules/npm/node_modules/spdx-correct": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -16285,12 +17680,16 @@ }, "node_modules/npm/node_modules/spdx-exceptions": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true, "inBundle": true, "license": "CC-BY-3.0" }, "node_modules/npm/node_modules/spdx-expression-parse": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "inBundle": true, "license": "MIT", @@ -16301,6 +17700,8 @@ }, "node_modules/npm/node_modules/spdx-license-ids": { "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true, "inBundle": true, "license": "CC0-1.0" @@ -16319,6 +17720,8 @@ }, "node_modules/npm/node_modules/string_decoder": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "inBundle": true, "license": "MIT", @@ -16328,6 +17731,8 @@ }, "node_modules/npm/node_modules/string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "inBundle": true, "license": "MIT", @@ -16343,6 +17748,8 @@ "node_modules/npm/node_modules/string-width-cjs": { "name": "string-width", "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "inBundle": true, "license": "MIT", @@ -16357,6 +17764,8 @@ }, "node_modules/npm/node_modules/strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "inBundle": true, "license": "MIT", @@ -16370,6 +17779,8 @@ "node_modules/npm/node_modules/strip-ansi-cjs": { "name": "strip-ansi", "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "inBundle": true, "license": "MIT", @@ -16382,6 +17793,8 @@ }, "node_modules/npm/node_modules/supports-color": { "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", "dev": true, "inBundle": true, "license": "MIT", @@ -16435,18 +17848,24 @@ }, "node_modules/npm/node_modules/text-table": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/tiny-relative-date": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz", + "integrity": "sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/treeverse": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-3.0.0.tgz", + "integrity": "sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -16456,6 +17875,8 @@ }, "node_modules/npm/node_modules/tuf-js": { "version": "1.1.7", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", + "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", "dev": true, "inBundle": true, "license": "MIT", @@ -16470,6 +17891,8 @@ }, "node_modules/npm/node_modules/unique-filename": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", "dev": true, "inBundle": true, "license": "ISC", @@ -16482,6 +17905,8 @@ }, "node_modules/npm/node_modules/unique-slug": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -16500,6 +17925,8 @@ }, "node_modules/npm/node_modules/validate-npm-package-license": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -16510,6 +17937,8 @@ }, "node_modules/npm/node_modules/validate-npm-package-name": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -16522,12 +17951,16 @@ }, "node_modules/npm/node_modules/walk-up-path": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", + "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/wcwidth": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, "inBundle": true, "license": "MIT", @@ -16537,6 +17970,8 @@ }, "node_modules/npm/node_modules/which": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", "dev": true, "inBundle": true, "license": "ISC", @@ -16552,6 +17987,8 @@ }, "node_modules/npm/node_modules/wide-align": { "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "dev": true, "inBundle": true, "license": "ISC", @@ -16596,6 +18033,8 @@ }, "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, "inBundle": true, "license": "MIT", @@ -16620,6 +18059,8 @@ }, "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, "inBundle": true, "license": "MIT" @@ -16643,6 +18084,8 @@ }, "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -16664,6 +18107,8 @@ }, "node_modules/npm/node_modules/write-file-atomic": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, "inBundle": true, "license": "ISC", @@ -16840,7 +18285,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -16987,6 +18431,25 @@ "node": ">=6" } }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -17114,8 +18577,7 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -17538,6 +19000,14 @@ "node": ">= 0.8" } }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -17826,7 +19296,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -18173,9 +19642,9 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/react-player": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/react-player/-/react-player-2.12.0.tgz", - "integrity": "sha512-rymLRz/2GJJD+Wc01S7S+i9pGMFYnNmQibR2gVE3KmHJCBNN8BhPAlOPTGZtn1uKpJ6p4RPLlzPQ1OLreXd8gw==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/react-player/-/react-player-2.13.0.tgz", + "integrity": "sha512-gkY7ZdbVFztlKFFhCPcnDrFQm+L399b8fhWsKatZ+b2wpKJwfUHBXQFMRxqYQGT0ic1/wQ7D7EZEWy7ZBqk2pw==", "dependencies": { "deepmerge": "^4.0.0", "load-script": "^1.0.0", @@ -18296,6 +19765,26 @@ "unzipper": "^0.10.11" } }, + "node_modules/read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -18402,7 +19891,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -18649,6 +20137,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-mdx": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-2.3.0.tgz", + "integrity": "sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==", + "dependencies": { + "mdast-util-mdx": "^2.0.0", + "micromark-extension-mdxjs": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-parse": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz", @@ -18737,6 +20238,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-stringify": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-10.0.3.tgz", + "integrity": "sha512-koyOzCMYoUHudypbj4XpnAKFbkddRMYZHwghnxd7ue5210WzGw6kOBwauJTRUMq16jsovXx8dYNvSSWP89kZ3A==", + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-markdown": "^1.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/request-progress": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", @@ -18839,7 +20354,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -18946,31 +20460,85 @@ "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", "dev": true, "dependencies": { - "@types/node": "*", + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/rtcpeerconnection-shim": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.15.tgz", + "integrity": "sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw==", + "dependencies": { + "sdp": "^2.6.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=3.10.0" + } + }, + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/rtcpeerconnection-shim": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.15.tgz", - "integrity": "sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw==", - "dependencies": { - "sdp": "^2.6.0" + "node_modules/run-applescript/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "engines": { - "node": ">=6.0.0", - "npm": ">=3.10.0" + "node": ">=10.17.0" } }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -19268,8 +20836,7 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/simple-update-notifier": { "version": "1.1.0", @@ -19516,7 +21083,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -19647,6 +21213,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/stringify-entities": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.3.tgz", + "integrity": "sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/stringify-object": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", @@ -19706,7 +21285,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, "engines": { "node": ">=6" } @@ -19822,6 +21400,21 @@ "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.17.tgz", "integrity": "sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==" }, + "node_modules/synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dependencies": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/tailwindcss": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", @@ -20190,6 +21783,17 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" }, + "node_modules/titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", @@ -20227,6 +21831,19 @@ "node": ">=8.0" } }, + "node_modules/to-vfile": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/to-vfile/-/to-vfile-7.2.4.tgz", + "integrity": "sha512-2eQ+rJ2qGbyw3senPI0qjuM7aut8IYXK6AEoOWb+fJx/mQYzviTckm1wDjq91QYHAPBTYzmdJXxMFA6Mk14mdw==", + "dependencies": { + "is-buffer": "^2.0.0", + "vfile": "^5.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/tocbot": { "version": "4.21.0", "resolved": "https://registry.npmjs.org/tocbot/-/tocbot-4.21.0.tgz", @@ -20486,8 +22103,7 @@ "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "node_modules/typescript": { "version": "5.1.6", @@ -20587,6 +22203,120 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unified-engine": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/unified-engine/-/unified-engine-10.1.0.tgz", + "integrity": "sha512-5+JDIs4hqKfHnJcVCxTid1yBoI/++FfF/1PFdSMpaftZZZY+qg2JFruRbf7PaIwa9KgLotXQV3gSjtY0IdcFGQ==", + "dependencies": { + "@types/concat-stream": "^2.0.0", + "@types/debug": "^4.0.0", + "@types/is-empty": "^1.0.0", + "@types/node": "^18.0.0", + "@types/unist": "^2.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.0.0", + "fault": "^2.0.0", + "glob": "^8.0.0", + "ignore": "^5.0.0", + "is-buffer": "^2.0.0", + "is-empty": "^1.0.0", + "is-plain-obj": "^4.0.0", + "load-plugin": "^5.0.0", + "parse-json": "^6.0.0", + "to-vfile": "^7.0.0", + "trough": "^2.0.0", + "unist-util-inspect": "^7.0.0", + "vfile-message": "^3.0.0", + "vfile-reporter": "^7.0.0", + "vfile-statistics": "^2.0.0", + "yaml": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified-engine/node_modules/@types/node": { + "version": "18.18.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz", + "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==" + }, + "node_modules/unified-engine/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/unified-engine/node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/unified-engine/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/unified-engine/node_modules/lines-and-columns": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", + "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/unified-engine/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/unified-engine/node_modules/parse-json": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-6.0.2.tgz", + "integrity": "sha512-SA5aMiaIjXkAiBrW/yPgLgQAQg42f7K3ACO+2l/zOvtQBwX58DMUsFJXelW2fx3yMBmWOVkR6j1MGsdSbCA4UA==", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "error-ex": "^1.3.2", + "json-parse-even-better-errors": "^2.3.1", + "lines-and-columns": "^2.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -20608,6 +22338,18 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-inspect": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/unist-util-inspect/-/unist-util-inspect-7.0.2.tgz", + "integrity": "sha512-Op0XnmHUl6C2zo/yJCwhXQSm/SmW22eDZdWP2qdf4WpGrgO1ZxFodq+5zFyeRGasFjJotAnLgfuD1jkcKqiH1Q==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-is": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", @@ -20632,6 +22374,31 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-position-from-estree": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.2.tgz", + "integrity": "sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-4.0.2.tgz", + "integrity": "sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-stringify-position": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", @@ -20713,7 +22480,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, "engines": { "node": ">=8" } @@ -20887,9 +22653,13 @@ } }, "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -21017,6 +22787,103 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/vfile-reporter": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-7.0.5.tgz", + "integrity": "sha512-NdWWXkv6gcd7AZMvDomlQbK3MqFWL1RlGzMn++/O2TI+68+nqxCPTvLugdOtfSzXmjh+xUyhp07HhlrbJjT+mw==", + "dependencies": { + "@types/supports-color": "^8.0.0", + "string-width": "^5.0.0", + "supports-color": "^9.0.0", + "unist-util-stringify-position": "^3.0.0", + "vfile": "^5.0.0", + "vfile-message": "^3.0.0", + "vfile-sort": "^3.0.0", + "vfile-statistics": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-reporter/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/vfile-reporter/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vfile-reporter/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/vfile-reporter/node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/vfile-sort": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-3.0.1.tgz", + "integrity": "sha512-1os1733XY6y0D5x0ugqSeaVJm9lYgj0j5qdcZQFyxlZOSy1jYarL77lLyb5gK4Wqr1d5OxmuyflSO3zKyFnTFw==", + "dependencies": { + "vfile": "^5.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-statistics": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-2.0.1.tgz", + "integrity": "sha512-W6dkECZmP32EG/l+dp2jCLdYzmnDBIw6jwiLZSER81oR5AHRcVqL+k3Z+pfH1R73le6ayDkJRMk0sutj1bMVeg==", + "dependencies": { + "vfile": "^5.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/vite": { "version": "4.4.7", "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.7.tgz", @@ -21116,6 +22983,11 @@ "node": ">=0.10.0" } }, + "node_modules/walk-up-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", + "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==" + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -21747,7 +23619,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", - "dev": true, "engines": { "node": ">= 14" } diff --git a/package.json b/package.json index 246734dc3d4..1ec0e88f48f 100644 --- a/package.json +++ b/package.json @@ -69,10 +69,11 @@ "dayjs": "^1.11.9", "echarts": "^5.4.2", "echarts-for-react": "^3.0.2", + "eslint-mdx": "^2.2.0", "events": "^3.3.0", "i18next": "^23.2.7", "i18next-browser-languagedetector": "^7.1.0", - "lodash": "^4.17.21", + "lodash-es": "^4.17.21", "postcss-loader": "^7.3.3", "qrcode.react": "^3.1.0", "raviger": "^4.1.2", @@ -86,7 +87,7 @@ "react-google-recaptcha": "^3.1.0", "react-i18next": "^13.0.1", "react-markdown": "^8.0.7", - "react-player": "^2.12.0", + "react-player": "^2.13.0", "react-qr-reader": "^2.2.1", "react-redux": "^8.1.1", "react-transition-group": "^4.4.5", @@ -97,7 +98,7 @@ "rehype-raw": "^6.1.1", "rescript-webapi": "^0.8.0", "use-keyboard-shortcut": "^1.1.6", - "uuid": "^9.0.0" + "uuid": "^9.0.1" }, "devDependencies": { "@storybook/addon-essentials": "^7.0.26", @@ -113,7 +114,7 @@ "@types/cypress": "^1.1.3", "@types/echarts": "^4.9.18", "@types/google.maps": "^3.53.4", - "@types/lodash": "^4.14.195", + "@types/lodash-es": "^4.17.9", "@types/lodash.get": "^4.4.7", "@types/node": "^20.4.0", "@types/prop-types": "*", @@ -137,6 +138,7 @@ "eslint-plugin-i18next": "^6.0.3", "eslint-plugin-import": "^2.27.5", "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-mdx": "^2.2.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-only-warn": "^1.1.0", "eslint-plugin-prettier": "^4.2.1", @@ -182,21 +184,6 @@ "git update-index --again" ] }, - "eslintConfig": { - "extends": [ - "react-app" - ], - "overrides": [ - { - "files": [ - "**/*.stories.*" - ], - "rules": { - "import/no-anonymous-default-export": "off" - } - } - ] - }, "engines": { "node": "18.x" } diff --git a/public/config.json b/public/config.json index 8bb0dab3b57..444362cfb20 100644 --- a/public/config.json +++ b/public/config.json @@ -5,12 +5,12 @@ "site_url": "care.coronasafe.in", "analytics_server_url": "https://plausible.10bedicu.in", "header_logo": { - "light":"https://cdn.coronasafe.network/header_logo.png", - "dark":"https://cdn.coronasafe.network/header_logo.png" + "light": "https://cdn.coronasafe.network/header_logo.png", + "dark": "https://cdn.coronasafe.network/header_logo.png" }, "main_logo": { - "light":"https://cdn.coronasafe.network/light-logo.svg", - "dark":"https://cdn.coronasafe.network/black-logo.svg" + "light": "https://cdn.coronasafe.network/light-logo.svg", + "dark": "https://cdn.coronasafe.network/black-logo.svg" }, "gmaps_api_key": "AIzaSyDsBAc3y7deI5ZO3NtK5GuzKwtUzQNJNUk", "gov_data_api_key": "579b464db66ec23bdd000001cdd3946e44ce4aad7209ff7b23ac571b", diff --git a/src/CAREUI/display/Chip.tsx b/src/CAREUI/display/Chip.tsx index abc21711551..7bcbd6078e4 100644 --- a/src/CAREUI/display/Chip.tsx +++ b/src/CAREUI/display/Chip.tsx @@ -11,6 +11,7 @@ interface Props { text: string; tooltip?: string; className?: string; + id?: string; } export default function Chip({ @@ -21,6 +22,7 @@ export default function Chip({ }: Props) { return ( { > {`${name}: ${value}`} diff --git a/src/CAREUI/display/RecordMeta.tsx b/src/CAREUI/display/RecordMeta.tsx index 83928f1f23a..48cc8d370ad 100644 --- a/src/CAREUI/display/RecordMeta.tsx +++ b/src/CAREUI/display/RecordMeta.tsx @@ -11,13 +11,14 @@ interface Props { last_name: string; last_login: string | undefined; }; + inlineUser?: boolean; } /** * A generic component to display relative time along with a tooltip and a user * if provided. */ -const RecordMeta = ({ time, user, prefix, className }: Props) => { +const RecordMeta = ({ time, user, prefix, className, inlineUser }: Props) => { const isOnline = user && isUserOnline(user); let child = ( @@ -25,14 +26,15 @@ const RecordMeta = ({ time, user, prefix, className }: Props) => { {relativeTime(time)} {formatDateTime(time)} - {user && ( - <> + {user && !inlineUser && ( + + by {user.first_name} {user.last_name} {isOnline && ( -
+
)} - + )}
@@ -43,7 +45,13 @@ const RecordMeta = ({ time, user, prefix, className }: Props) => {
{prefix} {child} + {user && inlineUser && by} {user && } + {user && inlineUser && ( + + {user.first_name} {user.last_name} + + )}
); } diff --git a/src/CAREUI/interactive/FiltersSlideover.tsx b/src/CAREUI/interactive/FiltersSlideover.tsx index f396f03da79..9b2e5a29c29 100644 --- a/src/CAREUI/interactive/FiltersSlideover.tsx +++ b/src/CAREUI/interactive/FiltersSlideover.tsx @@ -3,11 +3,12 @@ import useFilters from "../../Common/hooks/useFilters"; import ButtonV2 from "../../Components/Common/components/ButtonV2"; import CareIcon from "../icons/CareIcon"; import SlideOver from "./SlideOver"; +import { ReactNode } from "react"; type AdvancedFilter = ReturnType["advancedFilter"]; interface Props { - children: any; + children: ReactNode | ReactNode[]; advancedFilter: AdvancedFilter; onClear?: () => void; onApply?: () => void; diff --git a/src/CAREUI/misc/PaginatedList.tsx b/src/CAREUI/misc/PaginatedList.tsx index 28ee17650ad..3521807154e 100644 --- a/src/CAREUI/misc/PaginatedList.tsx +++ b/src/CAREUI/misc/PaginatedList.tsx @@ -24,13 +24,13 @@ function useContextualized() { const ctx = useContext(context); if (ctx === null) { - throw new Error("PaginatedList must be used within a PaginatedList"); + throw new Error("Component must be used within a PaginatedList"); } return ctx as PaginatedListContext; } -interface Props extends QueryOptions { +interface Props extends QueryOptions> { route: QueryRoute>; perPage?: number; children: (ctx: PaginatedListContext) => JSX.Element | JSX.Element[]; @@ -42,11 +42,15 @@ export default function PaginatedList({ perPage = DEFAULT_PER_PAGE_LIMIT, ...queryOptions }: Props) { + const [currentPage, setPage] = useState(1); const query = useQuery(route, { ...queryOptions, - query: { ...queryOptions.query, limit: perPage }, + query: { + ...queryOptions.query, + limit: perPage, + offset: (currentPage - 1) * perPage, + }, }); - const [currentPage, setPage] = useState(1); const items = query.data?.results ?? []; diff --git a/src/Common/constants.tsx b/src/Common/constants.tsx index f64a9fa27ae..0b08b4b9a42 100644 --- a/src/Common/constants.tsx +++ b/src/Common/constants.tsx @@ -499,6 +499,7 @@ export const TELEMEDICINE_ACTIONS = [ { id: 60, text: "COMPLETE", desc: "Complete" }, { id: 70, text: "REVIEW", desc: "Review" }, { id: 80, text: "NOT_REACHABLE", desc: "Not Reachable" }, + { id: 90, text: "DISCHARGE_RECOMMENDED", desc: "Discharge Recommended" }, ]; export const FRONTLINE_WORKER = [ @@ -896,7 +897,7 @@ export const XLSXAssetImportSchema = { Class: { prop: "asset_class", type: String, - oneOf: ["HL7MONITOR", "ONVIF"], + oneOf: ["HL7MONITOR", "ONVIF", "VENTILATOR", ""], }, Description: { prop: "description", type: String }, "Working Status": { @@ -908,7 +909,7 @@ export const XLSXAssetImportSchema = { } else if (status === "NOT WORKING") { return false; } else { - throw new Error("Invalid Working Status"); + throw new Error("Invalid Working Status: " + status); } }, required: true, @@ -917,6 +918,7 @@ export const XLSXAssetImportSchema = { prop: "not_working_reason", type: String, }, + "Serial Number": { prop: "serial_number", type: String }, "QR Code ID": { prop: "qr_code_id", type: String }, Manufacturer: { prop: "manufacturer", type: String }, "Vendor Name": { prop: "vendor_name", type: String }, @@ -925,10 +927,11 @@ export const XLSXAssetImportSchema = { prop: "support_email", type: String, parse: (email: string) => { + if (!email) return null; const isValid = /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/.test(email); if (!isValid) { - throw new Error("Invalid Support Email"); + throw new Error("Invalid Support Email: " + email); } return email; @@ -938,23 +941,38 @@ export const XLSXAssetImportSchema = { prop: "support_phone", type: String, parse: (phone: number | string) => { - phone = "+91" + String(phone); - if (!PhoneNumberValidator(["support"])(phone) === undefined) { - throw new Error("Invalid Support Phone Number"); + phone = String(phone); + if (phone.length === 10 && !phone.startsWith("1800")) { + phone = "+91" + phone; + } + if (phone.startsWith("91") && phone.length === 12) { + phone = "+" + phone; + } + if (phone.startsWith("+911800")) { + phone = "1800" + phone.slice(6); + } + if ( + PhoneNumberValidator(["mobile", "landline", "support"])(phone) !== + undefined + ) { + throw new Error("Invalid Support Phone Number: " + phone); } return phone ? phone : undefined; }, required: true, }, - "Warrenty End Date": { + "Warranty End Date": { prop: "warranty_amc_end_of_validity", type: String, parse: (date: string) => { - const parsed = new Date(date); + if (!date) return null; + const parts = date.split("-"); + const reformattedDateStr = `${parts[2]}-${parts[1]}-${parts[0]}`; + const parsed = new Date(reformattedDateStr); if (String(parsed) === "Invalid Date") { - throw new Error("Invalid Warrenty End Date"); + throw new Error("Invalid Warranty End Date:" + date); } return dateQueryString(parsed); @@ -964,10 +982,13 @@ export const XLSXAssetImportSchema = { prop: "last_serviced_on", type: String, parse: (date: string) => { - const parsed = new Date(date); + if (!date) return null; + const parts = date.split("-"); + const reformattedDateStr = `${parts[2]}-${parts[1]}-${parts[0]}`; + const parsed = new Date(reformattedDateStr); if (String(parsed) === "Invalid Date") { - throw new Error("Invalid Last Service Date"); + throw new Error("Invalid Last Service Date:" + date); } return dateQueryString(parsed); @@ -981,13 +1002,14 @@ export const XLSXAssetImportSchema = { prop: "local_ip_address", type: String, parse: (ip: string) => { + if (!ip) return null; const isValid = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test( ip ); if (!isValid) { - throw new Error("Invalid Config IP Address"); + throw new Error("Invalid Config IP Address: " + ip); } return ip; diff --git a/src/Common/hooks/useAsyncOptions.ts b/src/Common/hooks/useAsyncOptions.ts index f0a1c895430..2f3f68d5c3a 100644 --- a/src/Common/hooks/useAsyncOptions.ts +++ b/src/Common/hooks/useAsyncOptions.ts @@ -1,4 +1,4 @@ -import { debounce } from "lodash"; +import { debounce } from "lodash-es"; import { useMemo, useState } from "react"; import { useDispatch } from "react-redux"; diff --git a/src/Common/hooks/useConfig.ts b/src/Common/hooks/useConfig.ts index 7b956afec07..15e456ea571 100644 --- a/src/Common/hooks/useConfig.ts +++ b/src/Common/hooks/useConfig.ts @@ -68,6 +68,7 @@ export interface IConfig { * Env to toggle peacetime and wartime shifting */ wartime_shifting: boolean; + jwt_token_refresh_interval?: number; } const useConfig = () => { diff --git a/src/Common/hooks/useMSEplayer.ts b/src/Common/hooks/useMSEplayer.ts index b14f94a6a43..fcbf216ed6a 100644 --- a/src/Common/hooks/useMSEplayer.ts +++ b/src/Common/hooks/useMSEplayer.ts @@ -208,6 +208,9 @@ export const useMSEMediaPlayer = ({ readPacket(event.data); } }; + ws.onerror = function (event) { + onError && onError(event); + }; }, false ); diff --git a/src/Common/hooks/useRangePagination.ts b/src/Common/hooks/useRangePagination.ts index e6bbe9f573e..7652ae546c1 100644 --- a/src/Common/hooks/useRangePagination.ts +++ b/src/Common/hooks/useRangePagination.ts @@ -9,18 +9,17 @@ interface Props { bounds: DateRange; perPage: number; slots?: number; - snapToLatest?: boolean; - reverse?: boolean; + defaultEnd?: boolean; } const useRangePagination = ({ bounds, perPage, ...props }: Props) => { const [currentRange, setCurrentRange] = useState( - getInitialBounds(bounds, perPage, props.snapToLatest) + getInitialBounds(bounds, perPage, props.defaultEnd) ); useEffect(() => { - setCurrentRange(getInitialBounds(bounds, perPage, props.snapToLatest)); - }, [bounds, perPage, props.snapToLatest]); + setCurrentRange(getInitialBounds(bounds, perPage, props.defaultEnd)); + }, [bounds, perPage, props.defaultEnd]); const next = () => { const { end } = currentRange; @@ -63,24 +62,17 @@ const useRangePagination = ({ bounds, perPage, ...props }: Props) => { } const slots: DateRange[] = []; - const { start, end } = currentRange; + const { start } = currentRange; const delta = perPage / props.slots; for (let i = 0; i < props.slots; i++) { - if (props.snapToLatest) { - slots.push({ - start: new Date(end.valueOf() - delta * (i - 1)), - end: new Date(end.valueOf() - delta * i), - }); - } else { - slots.push({ - start: new Date(start.valueOf() + delta * i), - end: new Date(start.valueOf() + delta * (i + 1)), - }); - } + slots.push({ + start: new Date(start.valueOf() + delta * i), + end: new Date(start.valueOf() + delta * (i + 1)), + }); } - return props.reverse ? slots.reverse() : slots; + return slots; }, [currentRange, props.slots, perPage]); return { @@ -98,7 +90,7 @@ export default useRangePagination; const getInitialBounds = ( bounds: DateRange, perPage: number, - snapToLatest?: boolean + defaultEnd?: boolean ) => { const deltaBounds = bounds.end.valueOf() - bounds.start.valueOf(); @@ -106,7 +98,7 @@ const getInitialBounds = ( return bounds; } - if (snapToLatest) { + if (defaultEnd) { return { start: new Date(bounds.end.valueOf() - perPage), end: bounds.end, diff --git a/src/Common/hooks/useSlug.ts b/src/Common/hooks/useSlug.ts new file mode 100644 index 00000000000..69d8f591c84 --- /dev/null +++ b/src/Common/hooks/useSlug.ts @@ -0,0 +1,45 @@ +import { usePath } from "raviger"; + +/** + * Returns the slug from the current path. + * @param prefix The prefix of the slug. + * @returns The slug. + * @example + * // Current path: /consultation/94b9a + * const consultation = useSlug("consultation"); // consultation = "94b9a" + */ +export default function useSlug(prefix: string) { + const path = usePath() ?? ""; + return findSlug(path.split("/"), prefix); +} + +/** + * Returns the slugs from the current path. + * @param prefix The prefixes of the slug. + * @returns The slugs + * @example + * // Current path: /facility/5b0a/consultation/94b9a + * const [facility, consultation] = useSlug("facility", "consultation"); + * // facility = "5b0a" + * // consultation = "94b9a" + */ +export const useSlugs = (...prefix: string[]) => { + const path = usePath() ?? ""; + return prefix.map((p) => findSlug(path.split("/"), p)); +}; + +const findSlug = (segments: string[], prefix: string) => { + const index = segments.findIndex((segment) => segment === prefix); + if (index === -1) { + throw new Error( + `Prefix "${prefix}" not found in path "${segments.join("/")}"` + ); + } + + const slug = segments[index + 1]; + if (!slug) { + throw new Error(`Slug not found in path "${segments.join("/")}"`); + } + + return slug; +}; diff --git a/src/Components/ABDM/ABHAProfileModal.tsx b/src/Components/ABDM/ABHAProfileModal.tsx index 0d6b7d9b90b..cc16fd45b8d 100644 --- a/src/Components/ABDM/ABHAProfileModal.tsx +++ b/src/Components/ABDM/ABHAProfileModal.tsx @@ -5,9 +5,9 @@ import CareIcon from "../../CAREUI/icons/CareIcon"; import DialogModal from "../Common/Dialog"; import QRCode from "qrcode.react"; import { formatDateTime } from "../../Utils/utils"; -import { getAbhaCard } from "../../Redux/actions"; -import { useDispatch } from "react-redux"; import { useRef } from "react"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; interface IProps { patientId?: string; @@ -18,21 +18,24 @@ interface IProps { const ABHAProfileModal = ({ patientId, show, onClose, abha }: IProps) => { const printRef = useRef(null); - const dispatch = useDispatch(); const downloadAbhaCard = async (type: "pdf" | "png") => { if (!patientId) return; - const response = await dispatch(getAbhaCard(patientId, type)); + const { res, data } = await request(routes.abha.getAbhaCard, { + body: { + patient: patientId, + type: type, + }, + }); - if (response.status === 200 && response.data) { + if (res?.status === 200 && data) { if (type === "png") { const downloadLink = document.createElement("a"); - downloadLink.href = - "data:application/octet-stream;base64," + response.data; + downloadLink.href = "data:application/octet-stream;base64," + data; downloadLink.download = "abha.png"; downloadLink.click(); } else { - const htmlPopup = ``; + const htmlPopup = ``; const printWindow = window.open("", "PDF"); printWindow?.document.write(htmlPopup); diff --git a/src/Components/ABDM/ConfigureHealthFacility.tsx b/src/Components/ABDM/ConfigureHealthFacility.tsx index 025a3f0e862..16e6bf90ea4 100644 --- a/src/Components/ABDM/ConfigureHealthFacility.tsx +++ b/src/Components/ABDM/ConfigureHealthFacility.tsx @@ -1,12 +1,13 @@ -import { lazy, useCallback, useEffect, useReducer, useState } from "react"; -import { useDispatch } from "react-redux"; - -import { healthFacilityActions } from "../../Redux/actions"; +import { lazy, useReducer, useState } from "react"; import * as Notification from "../../Utils/Notifications.js"; import { navigate } from "raviger"; import { Cancel, Submit } from "../Common/components/ButtonV2"; import TextFormField from "../Form/FormFields/TextFormField"; import { classNames } from "../../Utils/utils"; +import useQuery from "../../Utils/request/useQuery"; +import routes from "../../Redux/api"; +import request from "../../Utils/request/request"; +import { FieldChangeEvent } from "../Form/FormFields/Utils.js"; const Loading = lazy(() => import("../Common/Loading")); const initForm = { @@ -40,32 +41,26 @@ const FormReducer = (state = initialState, action: any) => { export const ConfigureHealthFacility = (props: any) => { const [state, dispatch] = useReducer(FormReducer, initialState); const { facilityId } = props; - const dispatchAction: any = useDispatch(); const [isLoading, setIsLoading] = useState(false); - const fetchData = useCallback(async () => { - if (facilityId) { - setIsLoading(true); - const res = await dispatchAction(healthFacilityActions.read(facilityId)); - - if (res?.status === 200 && res?.data) { - const formData = { - ...state.form, - hf_id: res.data.hf_id, - health_facility: res.data, - }; - dispatch({ type: "set_form", form: formData }); + const { loading } = useQuery(routes.abha.getHealthFacility, { + pathParams: { facility_id: facilityId }, + silent: true, + onResponse(res) { + if (res.data) { + dispatch({ + type: "set_form", + form: { + ...state.form, + health_facility: res.data, + hf_id: res.data.hf_id, + }, + }); } + }, + }); - setIsLoading(false); - } - }, [dispatchAction, facilityId]); - - useEffect(() => { - fetchData(); - }, [dispatch, fetchData]); - - const handleSubmit = async (e: any) => { + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setIsLoading(true); @@ -78,27 +73,43 @@ export const ConfigureHealthFacility = (props: any) => { return; } - let res = null; + let response = null; + let responseData = null; if (state.form.health_facility) { - res = await dispatchAction( - healthFacilityActions.partialUpdate(facilityId, { - hf_id: state.form.hf_id, - }) + const { res, data } = await request( + routes.abha.partialUpdateHealthFacility, + { + pathParams: { + facility_id: facilityId, + }, + body: { + hf_id: state.form.hf_id, + }, + } ); + response = res; + responseData = data; } else if (state.form.hf_id === state.form.health_facility?.hf_id) { - res = await dispatchAction( - healthFacilityActions.registerService(facilityId) + const { res, data } = await request( + routes.abha.registerHealthFacilityAsService, + { + pathParams: { + facility_id: facilityId, + }, + } ); + response = res; + responseData = data; - if (res?.status === 200 && res?.data) { - if (res.data?.registered) { + if (response?.status === 200 && responseData) { + if (responseData?.registered) { dispatch({ type: "set_form", form: { ...state.form, health_facility: { ...state.form?.health_facility, - registered: res.data.registered, + registered: responseData.registered, }, }, }); @@ -112,43 +123,45 @@ export const ConfigureHealthFacility = (props: any) => { }); return; } else { - res = await dispatchAction( - healthFacilityActions.create({ + const { res, data } = await request(routes.abha.createHealthFacility, { + body: { facility: facilityId, hf_id: state.form.hf_id, - }) - ); + }, + }); + response = res; + responseData = data; } setIsLoading(false); - if (res && res.data) { + if (response && responseData) { Notification.Success({ msg: "Health Facility config updated successfully", }); navigate(`/facility/${facilityId}`); } else { - if (res?.data) + if (responseData) Notification.Error({ - msg: "Something went wrong: " + (res.data.detail || ""), + msg: "Something went wrong: " + (responseData.detail || ""), }); } setIsLoading(false); }; - const handleChange = (e: any) => { + const handleChange = (e: FieldChangeEvent) => { dispatch({ type: "set_form", form: { ...state.form, [e.name]: e.value }, }); }; - if (isLoading) { + if (loading || isLoading) { return ; } return (
-
handleSubmit(e)}> +
{ } required value={state.form.hf_id} - onChange={(e) => handleChange(e)} + onChange={handleChange} error={state.errors?.hf_id} />
-
+
navigate(`/facility/${facilityId}`)} /> { - const dispatch = useDispatch(); - const [qrValue, setQrValue] = useState(""); const [authMethods, setAuthMethods] = useState([]); const [selectedAuthMethod, setSelectedAuthMethod] = useState(""); @@ -187,23 +173,23 @@ const ScanABHAQRSection = ({ try { const abha = JSON.parse(value); - const res = await dispatch(linkViaQR(abha, patientId)); + const { res, data } = await request(routes.abha.linkViaQR, { + body: { ...abha, patientId }, + }); if (res?.status === 200 || res?.status === 202) { Notify.Success({ msg: "Request sent successfully" }); onSuccess?.({ - ...res.data, + ...data, abha_profile: { - ...res.data?.abha_profile, - healthIdNumber: res.data?.abha_profile?.abha_number, - healthId: res.data?.abha_profile?.health_id, + ...data?.abha_profile, + healthIdNumber: data?.abha_profile?.abha_number, + healthId: data?.abha_profile?.health_id, mobile: abha?.mobile, monthOfBirth: - res.data?.abha_profile?.date_of_birth?.split("-")[1], - dayOfBirth: - res.data?.abha_profile?.date_of_birth?.split("-")[2], - yearOfBirth: - res.data?.abha_profile?.date_of_birth?.split("-")[0], + data?.abha_profile?.date_of_birth?.split("-")[1], + dayOfBirth: data?.abha_profile?.date_of_birth?.split("-")[2], + yearOfBirth: data?.abha_profile?.date_of_birth?.split("-")[0], }, }); } else { @@ -256,29 +242,55 @@ const ScanABHAQRSection = ({ disabled={otp.length !== 6} onClick={async () => { let response = null; + let Rdata = null; + let Rerror = null; switch (selectedAuthMethod) { case "MOBILE_OTP": - response = await dispatch( - confirmWithMobileOtp(txnId, otp, patientId) - ); + { + const { res, data, error } = await request( + routes.abha.confirmWithMobileOtp, + { + body: { + otp: otp, + txnId: txnId, + patientId: patientId, + }, + } + ); + response = res; + Rdata = data; + Rerror = error; + } break; case "AADHAAR_OTP": - response = await dispatch( - confirmWithAadhaarOtp(txnId, otp, patientId) - ); + { + const { res, data, error } = await request( + routes.abha.confirmWithAadhaarOtp, + { + body: { + otp: otp, + txnId: txnId, + patientId: patientId, + }, + } + ); + response = res; + Rdata = data; + Rerror = error; + } break; } - if (response.status === 200) { - onSuccess?.(response.data); + if (response?.status === 200) { + onSuccess?.(Rdata); Notify.Success({ msg: "ABHA Number linked successfully", }); } else { Notify.Error({ - msg: response?.message ?? "Something went wrong!", + msg: Rerror ?? "Something went wrong!", }); } }} @@ -290,13 +302,14 @@ const ScanABHAQRSection = ({ {authMethods.map((method) => ( { - const response = await dispatch( - initiateAbdmAuthentication(method, qrValue) + const { res, data } = await request( + routes.abha.initiateAbdmAuthentication, + { body: { authMethod: method, healthid: qrValue } } ); - if (response.status === 200 && response?.data?.txnId) { + if (res?.status === 200 && data?.txnId) { setSelectedAuthMethod(method); - setTxnId(response.data.txnId); + setTxnId(data.txnId); } }} > @@ -308,11 +321,18 @@ const ScanABHAQRSection = ({ { - const response = await dispatch(searchByHealthId(qrValue)); - - if (response.status === 200 && response?.data?.authMethods) { + const { res, data } = await request( + routes.abha.searchByHealthId, + { + body: { + healthId: qrValue, + }, + } + ); + + if (res?.status === 200 && data?.authMethods) { setAuthMethods( - response.data.authMethods?.filter?.((method: string) => + data.authMethods?.filter?.((method: string) => supportedAuthMethods.find( (supported) => supported === method ) @@ -339,8 +359,6 @@ const VerifyAadhaarSection = ({ onVerified, onSignin, }: VerifyAadhaarSectionProps) => { - const dispatch = useDispatch(); - const [aadhaarNumber, setAadhaarNumber] = useState(""); const [aadhaarNumberError, setAadhaarNumberError] = useState(); @@ -382,17 +400,22 @@ const VerifyAadhaarSection = ({ if (!validateAadhaar()) return; setIsSendingOtp(true); - const res = await dispatch(generateAadhaarOtp(aadhaarNumber)); + + const { res, data } = await request(routes.abha.generateAadhaarOtp, { + body: { + aadhaar: aadhaarNumber, + }, + }); setIsSendingOtp(false); - if (res.status === 200 && res.data) { - const { txnId } = res.data; + if (res?.status === 200 && data) { + const { txnId } = data; setTxnId(txnId); Notify.Success({ msg: "OTP has been sent to the mobile number registered with the Aadhar number.", }); } else { - Notify.Error({ msg: JSON.stringify(res.data) }); + Notify.Error({ msg: JSON.stringify(data) }); } }; @@ -400,16 +423,20 @@ const VerifyAadhaarSection = ({ if (!validateAadhaar() || !txnId) return; setIsSendingOtp(true); - const res = await dispatch(resentAadhaarOtp(txnId)); + const { res, data } = await request(routes.abha.generateAadhaarOtp, { + body: { + txnId: txnId, + }, + }); setIsSendingOtp(false); - if (res.status === 200 && res.data.txnId) { - setTxnId(res.data.txnId); + if (res?.status === 200 && data?.txnId) { + setTxnId(data.txnId); Notify.Success({ msg: "OTP has been resent to the mobile number registered with the Aadhar number.", }); } else { - Notify.Error({ msg: JSON.stringify(res.data) }); + Notify.Error({ msg: JSON.stringify(data) }); } }; @@ -430,11 +457,16 @@ const VerifyAadhaarSection = ({ if (!validateOtp() || !txnId) return; setIsVerifyingOtp(true); - const res = await dispatch(verifyAadhaarOtp(txnId, otp)); + const { res, data } = await request(routes.abha.verifyAadhaarOtp, { + body: { + otp: otp, + txnId: txnId, + }, + }); setIsVerifyingOtp(false); - if (res.status === 200 && res.data.txnId) { - setTxnId(res.data.txnId); + if (res?.status === 200 && data?.txnId) { + setTxnId(data.txnId); Notify.Success({ msg: "OTP verified" }); setIsVerified(true); } else { @@ -563,8 +595,6 @@ const VerifyMobileSection = ({ onVerified, patientMobile, }: VerifyMobileSectionProps) => { - const dispatch = useDispatch(); - const [mobile, setMobile] = useState(() => patientMobile || ""); const [mobileError, setMobileError] = useState(); @@ -602,11 +632,16 @@ const VerifyMobileSection = ({ setOtpDispatched(false); setIsSendingOtp(true); - const res = await dispatch(checkAndGenerateMobileOtp(txnId, mobile)); + const { res, data } = await request(routes.abha.checkAndGenerateMobileOtp, { + body: { + mobile: mobile, + txnId: txnId, + }, + }); setIsSendingOtp(false); - if (res.status === 200 && res.data) { - const { txnId, mobileLinked } = res.data; + if (res?.status === 200 && data) { + const { txnId, mobileLinked } = data; setTxnId(txnId); if (mobileLinked) { @@ -621,7 +656,7 @@ const VerifyMobileSection = ({ }); } } else { - Notify.Error({ msg: JSON.stringify(res.data) }); + Notify.Error({ msg: JSON.stringify(data) }); } }; @@ -642,11 +677,16 @@ const VerifyMobileSection = ({ if (!validateOtp()) return; setIsVerifyingOtp(true); - const res = await dispatch(verifyMobileOtp(txnId, otp)); + const { res, data } = await request(routes.abha.verifyMobileOtp, { + body: { + txnId: txnId, + otp: otp, + }, + }); setIsVerifyingOtp(false); - if (res.status === 200 && res.data.txnId) { - setTxnId(res.data.txnId); + if (res?.status === 200 && data?.txnId) { + setTxnId(data.txnId); Notify.Success({ msg: "OTP verified" }); setIsVerified(true); } else { @@ -718,21 +758,24 @@ const CreateHealthIDSection = ({ onCreateSuccess, patientId, }: CreateHealthIDSectionProps) => { - const dispatch = useDispatch(); const [healthId, setHealthId] = useState(""); const [isCreating, setIsCreating] = useState(false); const [isHealthIdInputInFocus, setIsHealthIdInputInFocus] = useState(false); const handleCreateHealthId = async () => { setIsCreating(true); - const res = await dispatch( - createHealthId({ txnId: transactionId, patientId, healthId }) - ); - if (res.status === 200) { + const { res, data } = await request(routes.abha.createHealthId, { + body: { + healthId: healthId, + txnId: transactionId, + patientId: patientId, + }, + }); + if (res?.status === 200) { Notify.Success({ msg: "Abha Address created" }); - onCreateSuccess(res.data); + onCreateSuccess(data); } else { - Notify.Error({ msg: JSON.stringify(res.data) }); + Notify.Error({ msg: JSON.stringify(data) }); } setIsCreating(false); }; diff --git a/src/Components/ABDM/LinkCareContextModal.tsx b/src/Components/ABDM/LinkCareContextModal.tsx index fc0b488954d..36749ff3d23 100644 --- a/src/Components/ABDM/LinkCareContextModal.tsx +++ b/src/Components/ABDM/LinkCareContextModal.tsx @@ -5,9 +5,9 @@ import DateFormField from "../Form/FormFields/DateFormField"; import DialogModal from "../Common/Dialog"; import { PatientModel } from "../Patient/models"; import TextFormField from "../Form/FormFields/TextFormField"; -import { linkCareContext } from "../../Redux/actions"; -import { useDispatch } from "react-redux"; import { useState } from "react"; +import routes from "../../Redux/api.js"; +import request from "../../Utils/request/request.js"; interface IProps { consultationId: string; @@ -25,8 +25,6 @@ const LinkCareContextModal = ({ const [acceptedDisclaimer, setAcceptedDisclaimer] = useState(false); const [isLinkingCareContext, setIsLinkingCareContext] = useState(false); - const dispatch = useDispatch(); - return ( { setIsLinkingCareContext(true); - const res = await dispatch( - linkCareContext(consultationId, { + const { res } = await request(routes.abha.linkCareContext, { + body: { + consultation: consultationId, name: patient?.abha_number_object?.name, gender: patient?.abha_number_object?.gender, dob: patient?.abha_number_object?.date_of_birth, - }) - ); - - if (res.status === 202) { + }, + reattempts: 0, + }); + if (res?.status === 202) { Notification.Success({ msg: "Care Context sucessfully linked!", }); diff --git a/src/Components/ABDM/models.ts b/src/Components/ABDM/models.ts index b01579fba88..f992cc9df4f 100644 --- a/src/Components/ABDM/models.ts +++ b/src/Components/ABDM/models.ts @@ -17,3 +17,84 @@ export interface ICreateHealthIdResponse { healthId?: string; healthIdNumber: string; } + +export interface IHealthFacility { + id: string; + registered: boolean; + external_id: string; + created_date: string; + modified_date: string; + hf_id: string; + facility: string; + detail?: string; +} + +export interface ILinkABHANumber { + abha_profile: { + abha_number: string; + health_id: string; + date_of_birth: string; + }; +} + +export interface IConfirmMobileOtp { + otp: string; + txnId: string; + patientId?: string; + message?: string; +} + +export interface IHealthId { + authMethods?: string[]; +} + +export interface IAadhaarOtp { + txnId: string; +} + +export interface ICheckAndGenerateMobileOtp { + mobileLinked: boolean; + txnId: string; +} + +export interface IAadhaarOtpTBody { + aadhaar?: string; + txnId?: string; +} + +export interface IVerifyAadhaarOtpTBody { + consultation?: string; + name?: string; + gender?: "M" | "F" | "O"; + dob?: string; + otp?: string; + txnId?: string; +} + +export interface IGenerateMobileOtpTBody { + mobile: string; + txnId: string; +} + +export interface ISearchByHealthIdTBody { + healthId: string; +} + +export interface IinitiateAbdmAuthenticationTBody { + authMethod: string; + healthid: string; +} + +export interface IgetAbhaCardTBody { + patient: string; + type: "pdf" | "png"; +} + +export interface IcreateHealthFacilityTBody { + facility: string; + hf_id: string; +} + +export interface IpartialUpdateHealthFacilityTBody { + hf_id: string; +} diff --git a/src/Components/Assets/AssetFilter.tsx b/src/Components/Assets/AssetFilter.tsx index 4fc4ff6d7f2..703dbe027d3 100644 --- a/src/Components/Assets/AssetFilter.tsx +++ b/src/Components/Assets/AssetFilter.tsx @@ -1,36 +1,59 @@ import { useState, useEffect, useCallback } from "react"; -import { useAbortableEffect, statusType } from "../../Common/utils"; import { navigate, useQueryParams } from "raviger"; import { FacilitySelect } from "../Common/FacilitySelect"; import { FacilityModel } from "../Facility/models"; -import { useDispatch } from "react-redux"; -import { - getFacilityAssetLocation, - getPermittedFacility, -} from "../../Redux/actions"; -import * as Notification from "../../Utils/Notifications.js"; import { LocationSelect } from "../Common/LocationSelect"; -import { AssetClass, AssetLocationObject } from "./AssetTypes"; +import { AssetClass } from "./AssetTypes"; import { FieldLabel } from "../Form/FormFields/FormField"; import { SelectFormField } from "../Form/FormFields/SelectFormField"; import FiltersSlideover from "../../CAREUI/interactive/FiltersSlideover"; +import routes from "../../Redux/api"; +import useQuery from "../../Utils/request/useQuery"; +import DateRangeFormField from "../Form/FormFields/DateRangeFormField"; +import dayjs from "dayjs"; +import { FieldChangeEvent } from "../Form/FormFields/Utils"; +import { DateRange } from "../Common/DateRangeInputV2"; +import { dateQueryString } from "../../Utils/utils"; -const initialLocation = { - id: "", +const getDate = (value: any) => + value && dayjs(value).isValid() && dayjs(value).toDate(); + +const initialFacilityState: FacilityModel = { + id: undefined, name: "", - description: "", - facility: { - id: "", - name: "", + read_cover_image_url: "", + facility_type: "", + address: "", + features: [], + location: { + latitude: 0, + longitude: 0, }, + oxygen_capacity: 0, + phone_number: "", + type_b_cylinders: 0, + type_c_cylinders: 0, + type_d_cylinders: 0, + middleware_address: "", + expected_type_b_cylinders: 0, + expected_type_c_cylinders: 0, + expected_type_d_cylinders: 0, + expected_oxygen_requirement: 0, + local_body_object: undefined, + district_object: undefined, + state_object: undefined, + ward_object: undefined, + modified_date: "", + created_date: "", + state: 0, + district: 0, + local_body: 0, + ward: 0, }; function AssetFilter(props: any) { const { filter, onChange, closeFilter } = props; - const dispatch: any = useDispatch(); - const [facility, setFacility] = useState({ name: "" }); - const [location, setLocation] = - useState(initialLocation); + const [facility, setFacility] = useState(initialFacilityState); const [asset_type, setAssetType] = useState( filter.asset_type ? filter.asset_type : "" ); @@ -38,20 +61,65 @@ function AssetFilter(props: any) { const [asset_class, setAssetClass] = useState( filter.asset_class || "" ); - const [facilityId, setFacilityId] = useState(filter.facility); + const [facilityId, setFacilityId] = useState(filter.facility); const [locationId, setLocationId] = useState(filter.location); + const [warrantyExpiry, setWarrantyExpiry] = useState({ + before: filter.warranty_amc_end_of_validity_before || null, + after: filter.warranty_amc_end_of_validity_after || null, + }); const [qParams, _] = useQueryParams(); + useQuery(routes.getPermittedFacility, { + pathParams: { id: facilityId }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { + const transformedData = { + id: Number(data.id), + name: data.name, + read_cover_image_url: data.read_cover_image_url, + facility_type: String(data.facility_type), + address: data.address, + features: data.features, + location: { + latitude: Number(data.latitude), + longitude: Number(data.longitude), + }, + oxygen_capacity: data.oxygen_capacity, + phone_number: data.phone_number, + type_b_cylinders: data.type_b_cylinders, + type_c_cylinders: data.type_c_cylinders, + type_d_cylinders: data.type_d_cylinders, + middleware_address: data.middleware_address, + expected_type_b_cylinders: data.expected_type_b_cylinders, + expected_type_c_cylinders: data.expected_type_c_cylinders, + expected_type_d_cylinders: data.expected_type_d_cylinders, + expected_oxygen_requirement: data.expected_oxygen_requirement, + local_body_object: data.local_body_object, + district_object: data.district_object, + state_object: data.state_object, + ward_object: data.ward_object, + modified_date: data.modified_date, + created_date: data.created_date, + state: data.state, + district: data.district, + local_body: data.local_body, + ward: data.ward, + }; + setFacility(transformedData); + } + }, + prefetch: !!facilityId, + }); + useEffect(() => { - setFacilityId(facility?.id ? facility?.id : ""); + setFacilityId(facility?.id ? `${facility?.id}` : ""); setLocationId( facility?.id === qParams.facility ? qParams.location ?? "" : "" ); - }, [facility, location]); + }, [facility.id, qParams.facility, qParams.location]); const clearFilter = useCallback(() => { - setLocation(initialLocation); - setFacility({ name: "" }); + setFacility(initialFacilityState); setAssetType(""); setAssetStatus(""); setAssetClass(""); @@ -63,55 +131,17 @@ function AssetFilter(props: any) { else navigate("/assets"); }, [qParams]); - const fetchFacility = useCallback( - async (status: statusType) => { - if (facilityId) { - const facilityData: any = await dispatch( - getPermittedFacility(facilityId) - ); - if (!status.aborted) { - setFacility(facilityData?.data); - } - } - }, - [filter.facility] - ); - - const fetchLocation = useCallback( - async (status: statusType) => { - if (locationId && facilityId) { - const [locationData]: any = await Promise.all([ - dispatch( - getFacilityAssetLocation(String(facilityId), String(locationId)) - ), - ]); - if (!status.aborted && locationData !== undefined) { - if (!locationData.data) - Notification.Error({ - msg: "Something went wrong..!", - }); - else { - setLocation(locationData.data); - } - } - } else { - setLocation(initialLocation); - } - }, - [filter.location] - ); - - useAbortableEffect((status: statusType) => { - filter.facility && fetchFacility(status); - filter.location && fetchLocation(status); - }, []); const applyFilter = () => { const data = { facility: facilityId, asset_type: asset_type ?? "", asset_class: asset_class ?? "", status: asset_status ?? "", - location: locationId, + location: locationId ?? "", + warranty_amc_end_of_validity_before: dateQueryString( + warrantyExpiry.before + ), + warranty_amc_end_of_validity_after: dateQueryString(warrantyExpiry.after), }; onChange(data); }; @@ -124,6 +154,13 @@ function AssetFilter(props: any) { setLocationId(selectedId); }; + const handleDateRangeChange = (event: FieldChangeEvent) => { + const state = { ...warrantyExpiry }; + state.after = event.value.start?.toString(); + state.before = event.value.end?.toString(); + setWarrantyExpiry(state); + }; + return ( setAssetClass(value)} /> + + ); } diff --git a/src/Components/Assets/AssetImportModal.tsx b/src/Components/Assets/AssetImportModal.tsx index 548df2901ec..02fe1d90265 100644 --- a/src/Components/Assets/AssetImportModal.tsx +++ b/src/Components/Assets/AssetImportModal.tsx @@ -5,10 +5,7 @@ import { FacilityModel } from "../Facility/models"; import { AssetData } from "./AssetTypes"; import * as Notification from "../../Utils/Notifications.js"; import { Cancel, Submit } from "../Common/components/ButtonV2"; -import { listFacilityAssetLocation } from "../../Redux/actions"; -import { useDispatch } from "react-redux"; import { Link } from "raviger"; -import SelectMenuV2 from "../Form/SelectMenuV2"; import readXlsxFile from "read-excel-file"; import { LocalStorageKeys, @@ -17,6 +14,9 @@ import { import { parseCsvFile } from "../../Utils/utils"; import useConfig from "../../Common/hooks/useConfig"; import DialogModal from "../Common/Dialog"; +import useQuery from "../../Utils/request/useQuery"; +import routes from "../../Redux/api"; +import { SelectFormField } from "../Form/FormFields/SelectFormField"; interface Props { open: boolean; @@ -25,13 +25,14 @@ interface Props { } const AssetImportModal = ({ open, onClose, facility }: Props) => { - const [isImporting, setIsUploading] = useState(false); + const [isImporting, setIsImporting] = useState(false); const [selectedFile, setSelectedFile] = useState(); const [preview, setPreview] = useState<(AssetData & { notes?: string; last_serviced_on?: string })[]>(); const [location, setLocation] = useState(""); - const [locations, setLocations] = useState([]); - const dispatchAction: any = useDispatch(); + const [errors, setErrors] = useState({ + location: "", + }); const { sample_format_asset_import } = useConfig(); const closeModal = () => { @@ -39,16 +40,11 @@ const AssetImportModal = ({ open, onClose, facility }: Props) => { setSelectedFile(undefined); onClose && onClose(); }; + const { data, loading } = useQuery(routes.listFacilityAssetLocation, { + pathParams: { facility_external_id: `${facility.id}` }, + }); - useEffect(() => { - dispatchAction( - listFacilityAssetLocation({}, { facility_external_id: facility.id }) - ).then(({ data }: any) => { - if (data.count > 0) { - setLocations(data.results); - } - }); - }, []); + const locations = data?.results || []; useEffect(() => { const readFile = async () => { @@ -85,11 +81,11 @@ const AssetImportModal = ({ open, onClose, facility }: Props) => { } } } - } catch (e) { + } catch (e: any) { setPreview(undefined); console.log(e); Notification.Error({ - msg: "Invalid file", + msg: "Invalid file: " + e.message, }); setSelectedFile(undefined); } @@ -110,10 +106,19 @@ const AssetImportModal = ({ open, onClose, facility }: Props) => { closeModal(); return; } + if (!location) { + setErrors({ + ...errors, + location: "Please select a location", + }); + return; + } + setIsImporting(true); let error = false; + Notification.Success({ msg: "Importing assets..." }); for (const asset of preview || []) { - const asset_data = JSON.stringify({ + const asset_data: any = { name: asset.name, asset_type: asset.asset_type, asset_class: asset.asset_class, @@ -129,11 +134,15 @@ const AssetImportModal = ({ open, onClose, facility }: Props) => { qr_code_id: asset.qr_code_id, manufacturer: asset.manufacturer, meta: { ...asset.meta }, - warranty_amc_end_of_validity: asset.warranty_amc_end_of_validity, - last_serviced_on: asset.last_serviced_on, note: asset.notes, - cancelToken: { promise: {} }, - }); + }; + + if (asset.last_serviced_on) + asset_data["last_serviced_on"] = asset.last_serviced_on; + + if (asset.warranty_amc_end_of_validity) + asset_data["warranty_amc_end_of_validity"] = + asset.warranty_amc_end_of_validity; const response = await fetch("/api/v1/asset/", { method: "POST", @@ -142,7 +151,7 @@ const AssetImportModal = ({ open, onClose, facility }: Props) => { Authorization: "Bearer " + localStorage.getItem(LocalStorageKeys.accessToken), }, - body: asset_data, + body: JSON.stringify(asset_data), }); const data = await response.json(); if (response.status !== 201) { @@ -152,16 +161,22 @@ const AssetImportModal = ({ open, onClose, facility }: Props) => { }); error = true; } else { - if (preview) setPreview(preview.filter((a) => a.id !== asset.id)); + setPreview((preview) => { + return preview?.slice(1); + }); } } if (!error) { Notification.Success({ msg: "Assets imported successfully" }); await sleep(1000); - setIsUploading(false); - closeModal(); + setIsImporting(false); window.location.reload(); - } else Notification.Error({ msg: "Error importing some assets" }); + } else { + Notification.Error({ msg: "Error importing some assets" }); + await sleep(1000); + setIsImporting(false); + closeModal(); + } }; const dragProps = useDragAndDrop(); @@ -189,7 +204,7 @@ const AssetImportModal = ({ open, onClose, facility }: Props) => { fixedWidth={false} > {facility.name} - {locations.length === 0 ? ( + {!loading && locations.length === 0 ? ( <>

@@ -214,31 +229,28 @@ const AssetImportModal = ({ open, onClose, facility }: Props) => { {preview && preview?.length > 0 ? (

- {preview.length} assets will be imported + {preview.length} assets {isImporting ? "are being" : "will be"}{" "} + imported

-
@@ -340,6 +352,7 @@ const AssetImportModal = ({ open, onClose, facility }: Props) => { {isImporting ? ( diff --git a/src/Components/Assets/AssetManage.tsx b/src/Components/Assets/AssetManage.tsx index 84325d704aa..4f65bc6a569 100644 --- a/src/Components/Assets/AssetManage.tsx +++ b/src/Components/Assets/AssetManage.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback, useEffect, ReactElement, lazy } from "react"; +import { useState, useEffect, ReactElement, lazy } from "react"; import { AssetClass, assetClassProps, @@ -6,14 +6,6 @@ import { AssetService, AssetTransaction, } from "./AssetTypes"; -import { statusType, useAbortableEffect } from "../../Common/utils"; -import { useDispatch } from "react-redux"; -import { - deleteAsset, - getAsset, - listAssetService, - listAssetTransaction, -} from "../../Redux/actions"; import Pagination from "../Common/Pagination"; import { navigate } from "raviger"; import QRCode from "qrcode.react"; @@ -34,7 +26,11 @@ import useAuthUser from "../../Common/hooks/useAuthUser"; import dayjs from "dayjs"; import RelativeDateUserMention from "../Common/RelativeDateUserMention"; import { AssetServiceEditModal } from "./AssetServiceEditModal"; +import { warrantyAmcValidityChip } from "./AssetsList"; import Page from "../Common/components/Page"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; +import useQuery from "../../Utils/request/useQuery"; interface AssetManageProps { assetId: string; @@ -50,80 +46,60 @@ const checkAuthority = (type: string, cutoff: string) => { const AssetManage = (props: AssetManageProps) => { const { t } = useTranslation(); const { assetId, facilityId } = props; - const [asset, setAsset] = useState(); const [isPrintMode, setIsPrintMode] = useState(false); const [currentPage, setCurrentPage] = useState(1); const [offset, setOffset] = useState(0); const [totalCount, setTotalCount] = useState(0); - const [transactions, setTransactions] = useState([]); const [transactionDetails, setTransactionDetails] = useState< ReactElement | ReactElement[] >(); - const [services, setServices] = useState([]); const [servicesDetails, setServiceDetails] = useState< ReactElement | ReactElement[] >(); - const [isLoading, setIsLoading] = useState(false); - const dispatch = useDispatch(); const limit = 14; const authUser = useAuthUser(); const [showDeleteDialog, setShowDeleteDialog] = useState(false); const [serviceEditData, setServiceEditData] = useState< AssetService & { open: boolean; viewOnly?: boolean } >(); + const [transactionFilter, setTransactionFilter] = useState({}); - const fetchData = useCallback( - async (status: statusType) => { - setIsLoading(true); - const assetData = await dispatch(getAsset(assetId)); - if (!status.aborted) { - setIsLoading(false); - if (assetData?.data) { - setAsset(assetData.data); - - const transactionFilter = assetData.qr_code_id - ? { qr_code_id: assetData.qr_code_id } - : { external_id: assetId }; - - const [transactionsData, servicesData] = await Promise.all([ - dispatch( - listAssetTransaction({ - ...transactionFilter, - limit, - offset, - }) - ), - dispatch(listAssetService({}, assetId)), - ]); - - if (transactionsData?.data) { - setTransactions(transactionsData.data.results); - setTotalCount(transactionsData.data.count); - } else { - Notification.Error({ - msg: "Error fetching transactions", - }); - } - if (servicesData?.data) { - setServices(servicesData.data.results); - } else { - Notification.Error({ - msg: "Error fetching service logs", - }); - } - } else { - navigate("/not-found"); - } + const { data: asset, loading } = useQuery(routes.getAsset, { + pathParams: { + external_id: assetId, + }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { + setTransactionFilter( + data.qr_code_id + ? { qr_code_id: data.qr_code_id } + : { external_id: assetId } + ); } }, - [dispatch, assetId, offset] - ); + }); - useAbortableEffect( - (status: statusType) => { - fetchData(status); + const { data: transactions } = useQuery(routes.listAssetTransaction, { + prefetch: !!asset, + query: { + ...transactionFilter, + limit, + offset, + }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { + setTotalCount(data.count); + } }, - [dispatch, fetchData] + }); + + const { data: services, refetch: serviceRefetch } = useQuery( + routes.listAssetService, + { + pathParams: { + asset_external_id: assetId, + }, + } ); const handlePagination = (page: number, limit: number) => { @@ -157,25 +133,25 @@ const AssetManage = (props: AssetManageProps) => { const populateTableRows = (txns: AssetTransaction[]) => { if (txns.length > 0) { setTransactionDetails( - transactions.map((transaction: AssetTransaction) => ( + transactions?.results.map((transaction: AssetTransaction) => ( {transaction.from_location.name} - + {transaction.to_location.name} - + {transaction.performed_by.first_name}{" "} {transaction.performed_by.last_name} - + {formatDateTime(transaction.modified_date)} @@ -200,9 +176,9 @@ const AssetManage = (props: AssetManageProps) => { const populateServiceTableRows = (txns: AssetService[]) => { if (txns.length > 0) { setServiceDetails( - services.map((service: AssetService) => ( + services?.results.map((service: AssetService) => ( - + {dayjs(service.serviced_on).format("DD MMM YYYY")} @@ -229,7 +205,7 @@ const AssetManage = (props: AssetManageProps) => { )} - + { }; useEffect(() => { - populateTableRows(transactions); + if (transactions) populateTableRows(transactions.results); }, [transactions]); useEffect(() => { - populateServiceTableRows(services); + if (services) populateServiceTableRows(services?.results); }, [services]); - if (isLoading) return ; + if (loading) return ; if (isPrintMode) return ; const assetClassProp = @@ -323,13 +299,17 @@ const AssetManage = (props: AssetManageProps) => { const handleDelete = async () => { if (asset) { - const response = await dispatch(deleteAsset(asset.id)); - if (response && response.status === 204) { - Notification.Success({ - msg: "Asset deleted successfully", - }); - navigate("/assets"); - } + await request(routes.deleteAsset, { + pathParams: { + external_id: asset.id, + }, + onResponse: () => { + Notification.Success({ + msg: "Asset deleted successfully", + }); + navigate("/assets"); + }, + }); } }; @@ -408,6 +388,9 @@ const AssetManage = (props: AssetManageProps) => { startIcon="l-times" /> )} + {warrantyAmcValidityChip( + asset?.warranty_amc_end_of_validity as string + )}

@@ -449,20 +432,24 @@ const AssetManage = (props: AssetManageProps) => { {t("update")} - {asset?.asset_class && ( - - navigate( - `/facility/${asset?.location_object.facility.id}/assets/${asset?.id}/configure` - ) - } - id="configure-asset" - data-testid="asset-configure-button" - > - - {t("configure")} - - )} + {asset?.asset_class && + (asset?.asset_class !== "ONVIF" || + ["DistrictAdmin", "StateAdmin", "Doctor"].includes( + authUser.user_type + )) && ( + + navigate( + `/facility/${asset?.location_object.facility.id}/assets/${asset?.id}/configure` + ) + } + id="configure-asset" + data-testid="asset-configure-button" + > + + {t("configure")} + + )} {checkAuthority(authUser.user_type, "DistrictAdmin") && ( { - - @@ -558,13 +545,13 @@ const AssetManage = (props: AssetManageProps) => { - - - @@ -591,7 +578,7 @@ const AssetManage = (props: AssetManageProps) => { handleClose={() => setServiceEditData({ ...serviceEditData, open: false }) } - handleUpdate={() => fetchData({ aborted: false })} + handleUpdate={() => serviceRefetch()} show={serviceEditData.open} viewOnly={serviceEditData.viewOnly} /> diff --git a/src/Components/Assets/AssetServiceEditModal.tsx b/src/Components/Assets/AssetServiceEditModal.tsx index 66d44d11907..3964dfe0770 100644 --- a/src/Components/Assets/AssetServiceEditModal.tsx +++ b/src/Components/Assets/AssetServiceEditModal.tsx @@ -1,16 +1,16 @@ import { useEffect, useState } from "react"; -import { useDispatch } from "react-redux"; -import { updateAssetService } from "../../Redux/actions"; import * as Notification from "../../Utils/Notifications.js"; import ButtonV2, { Cancel, Submit } from "../Common/components/ButtonV2"; import DialogModal from "../Common/Dialog"; import { AssetData, AssetService, AssetServiceEdit } from "./AssetTypes"; import dayjs from "dayjs"; import TextAreaFormField from "../Form/FormFields/TextAreaFormField"; -import DateInputV2 from "../Common/DateInputV2"; -import { FieldLabel } from "../Form/FormFields/FormField"; import { formatDate, formatDateTime } from "../../Utils/utils"; import CareIcon from "../../CAREUI/icons/CareIcon"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; +import DateFormField from "../Form/FormFields/DateFormField"; +import { t } from "i18next"; export const AssetServiceEditModal = (props: { asset?: AssetData; @@ -24,23 +24,25 @@ export const AssetServiceEditModal = (props: { serviced_on: props.service_record?.serviced_on, note: props.service_record?.note, }); - const dispatchAction: any = useDispatch(); const [isLoading, setIsLoading] = useState(false); const [editRecord, setEditRecord] = useState(); const handleSubmit = async (e: any) => { e.preventDefault(); setIsLoading(true); - const data = { + const body = { serviced_on: form.serviced_on, note: form.note, }; - - const res = await dispatchAction( - updateAssetService(props.asset?.id ?? "", props.service_record.id, data) - ); + const { data } = await request(routes.updateAssetService, { + pathParams: { + asset_external_id: props.asset?.id ?? "", + external_id: props.service_record.id, + }, + body: body, + }); setIsLoading(false); - if (res?.data) { + if (data) { Notification.Success({ msg: "Asset service record updated successfully", }); @@ -61,12 +63,12 @@ export const AssetServiceEditModal = (props: {

- Update record for asset + {t("update_record_for_asset")} {props.asset?.name}

@@ -110,13 +112,17 @@ export const AssetServiceEditModal = (props: {
-

Edited On

+

+ {t("edited_on")} +

{formatDateTime(editRecord.edited_on)}

-

Edited By

+

+ {t("edited_by")} +

{editRecord.edited_by.username}

@@ -125,7 +131,7 @@ export const AssetServiceEditModal = (props: {

- Serviced On + {t("serviced_on")}

-

Notes

+

+ {t("notes")} +

{editRecord.note || "-"}

@@ -151,7 +159,7 @@ export const AssetServiceEditModal = (props: { editRecord ? setEditRecord(undefined) : props.handleClose(); }} > - {editRecord ? "Back" : "Close"} + {editRecord ? t("back") : t("close")}
@@ -163,12 +171,12 @@ export const AssetServiceEditModal = (props: {

- Update record for asset + {t("update_record_for_asset")} {props.asset?.name}

@@ -178,19 +186,31 @@ export const AssetServiceEditModal = (props: { className="col-span-6 sm:col-span-3" data-testid="asset-last-serviced-on-input" > - Serviced On - { - setForm({ - ...form, - serviced_on: dayjs(date).format("YYYY-MM-DD"), - }); + if ( + dayjs(date.value).format("YYYY-MM-DD") > + new Date( + props.service_record.created_date + ).toLocaleDateString("en-ca") + ) { + Notification.Error({ + msg: `Service date can't be after ${formatDate( + props.service_record.created_date + )} (Creation date)`, + }); + } else { + setForm({ + ...form, + serviced_on: dayjs(date.value).format("YYYY-MM-DD"), + }); + } }} - max={new Date(props.service_record.created_date)} />
@@ -198,8 +218,8 @@ export const AssetServiceEditModal = (props: { { setForm({ ...form, note: e.value }); @@ -210,7 +230,7 @@ export const AssetServiceEditModal = (props: {
diff --git a/src/Components/Assets/AssetType/HL7Monitor.tsx b/src/Components/Assets/AssetType/HL7Monitor.tsx index 55f4d0c258e..b4fefbc90b2 100644 --- a/src/Components/Assets/AssetType/HL7Monitor.tsx +++ b/src/Components/Assets/AssetType/HL7Monitor.tsx @@ -1,10 +1,5 @@ import { SyntheticEvent, useEffect, useState } from "react"; import { AssetData } from "../AssetTypes"; -import { useDispatch } from "react-redux"; -import { - partialUpdateAsset, - getPermittedFacility, -} from "../../../Redux/actions"; import * as Notification from "../../../Utils/Notifications.js"; import MonitorConfigure from "../configure/MonitorConfigure"; import Loading from "../../Common/Loading"; @@ -16,6 +11,9 @@ import TextFormField from "../../Form/FormFields/TextFormField"; import HL7PatientVitalsMonitor from "../../VitalsMonitor/HL7PatientVitalsMonitor"; import VentilatorPatientVitalsMonitor from "../../VitalsMonitor/VentilatorPatientVitalsMonitor"; import useAuthUser from "../../../Common/hooks/useAuthUser"; +import request from "../../../Utils/request/request"; +import routes from "../../../Redux/api"; +import useQuery from "../../../Utils/request/useQuery"; interface HL7MonitorProps { assetId: string; @@ -33,19 +31,14 @@ const HL7Monitor = (props: HL7MonitorProps) => { const [localipAddress, setLocalIPAddress] = useState(""); const [ipadrdress_error, setIpAddress_error] = useState(""); const authUser = useAuthUser(); - const dispatch = useDispatch(); - - useEffect(() => { - const fetchFacility = async () => { - const res = await dispatch(getPermittedFacility(facilityId)); - - if (res.status === 200 && res.data) { - setFacilityMiddlewareHostname(res.data.middleware_address); + const { data: facility, loading } = useQuery(routes.getPermittedFacility, { + pathParams: { id: facilityId }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data && data.middleware_address) { + setFacilityMiddlewareHostname(data.middleware_address); } - }; - - if (facilityId) fetchFacility(); - }, [dispatch, facilityId]); + }, + }); useEffect(() => { setAssetType(asset?.asset_class); @@ -65,26 +58,28 @@ const HL7Monitor = (props: HL7MonitorProps) => { local_ip_address: localipAddress, }, }; - const res: any = await Promise.resolve( - dispatch(partialUpdateAsset(assetId, data)) - ); + const { res } = await request(routes.partialUpdateAsset, { + pathParams: { external_id: assetId }, + body: data, + }); if (res?.status === 200) { Notification.Success({ msg: "Asset Configured Successfully", }); } else { Notification.Error({ - msg: "Something went wrong..!", + msg: "Something went wrong!", }); } } else { - setIpAddress_error("Please Enter a Valid IP address !!"); + setIpAddress_error("IP address is invalid"); } }; - const middleware = middlewareHostname || facilityMiddlewareHostname; + const fallbackMiddleware = + asset?.location_object?.middleware_address || facilityMiddlewareHostname; - if (isLoading) return ; + if (isLoading || loading || !facility) return ; return (
@@ -93,11 +88,29 @@ const HL7Monitor = (props: HL7MonitorProps) => {

Connection

-
+
+

Middleware Hostname

+ {!middlewareHostname && ( +
+ + + Middleware hostname sourced from{" "} + {asset?.location_object?.middleware_address + ? "asset location" + : "asset facility"} + +
+ )} +
+ } + placeholder={fallbackMiddleware} value={middlewareHostname} onChange={(e) => setMiddlewareHostname(e.value)} errorClassName="hidden" @@ -127,12 +140,16 @@ const HL7Monitor = (props: HL7MonitorProps) => { {assetType === "HL7MONITOR" && ( )} {assetType === "VENTILATOR" && ( )}
diff --git a/src/Components/Assets/AssetType/ONVIFCamera.tsx b/src/Components/Assets/AssetType/ONVIFCamera.tsx index 4720c876010..4a3e475419e 100644 --- a/src/Components/Assets/AssetType/ONVIFCamera.tsx +++ b/src/Components/Assets/AssetType/ONVIFCamera.tsx @@ -1,11 +1,5 @@ import { useEffect, useState } from "react"; import { AssetData } from "../AssetTypes"; -import { useDispatch } from "react-redux"; -import { - partialUpdateAsset, - createAssetBed, - getPermittedFacility, -} from "../../../Redux/actions"; import * as Notification from "../../../Utils/Notifications.js"; import { BedModel } from "../../Facility/models"; import axios from "axios"; @@ -18,6 +12,12 @@ import { Submit } from "../../Common/components/ButtonV2"; import { SyntheticEvent } from "react"; import useAuthUser from "../../../Common/hooks/useAuthUser"; +import request from "../../../Utils/request/request"; +import routes from "../../../Redux/api"; +import useQuery from "../../../Utils/request/useQuery"; + +import CareIcon from "../../../CAREUI/icons/CareIcon"; + interface Props { assetId: string; facilityId: string; @@ -43,19 +43,15 @@ const ONVIFCamera = ({ assetId, facilityId, asset, onUpdated }: Props) => { const [refreshPresetsHash, setRefreshPresetsHash] = useState( Number(new Date()) ); - const dispatch = useDispatch(); + const { data: facility, loading } = useQuery(routes.getPermittedFacility, { + pathParams: { id: facilityId }, + }); const authUser = useAuthUser(); useEffect(() => { - const fetchFacility = async () => { - const res = await dispatch(getPermittedFacility(facilityId)); - - if (res.status === 200 && res.data) { - setFacilityMiddlewareHostname(res.data.middleware_address); - } - }; - - if (facilityId) fetchFacility(); - }, [dispatch, facilityId]); + if (facility?.middleware_address) { + setFacilityMiddlewareHostname(facility.middleware_address); + } + }, [facility, facilityId]); useEffect(() => { if (asset) { @@ -83,18 +79,19 @@ const ONVIFCamera = ({ assetId, facilityId, asset, onUpdated }: Props) => { camera_access_key: `${username}:${password}:${streamUuid}`, }, }; - const res: any = await Promise.resolve( - dispatch(partialUpdateAsset(assetId, data)) - ); + const { res } = await request(routes.partialUpdateAsset, { + pathParams: { external_id: assetId }, + body: data, + }); if (res?.status === 200) { Notification.Success({ msg: "Asset Configured Successfully" }); onUpdated?.(); } else { - Notification.Error({ msg: "Something went wrong..!" }); + Notification.Error({ msg: "Something went wrong!" }); } setLoadingSetConfiguration(false); } else { - setIpAddress_error("Please Enter a Valid Camera address !!"); + setIpAddress_error("IP address is invalid"); } }; @@ -110,15 +107,14 @@ const ONVIFCamera = ({ assetId, facilityId, asset, onUpdated }: Props) => { const presetData = await axios.get( `https://${facilityMiddlewareHostname}/status?hostname=${config.hostname}&port=${config.port}&username=${config.username}&password=${config.password}` ); - const res: any = await Promise.resolve( - dispatch( - createAssetBed( - { meta: { ...data, ...presetData.data } }, - assetId, - bed?.id as string - ) - ) - ); + + const { res } = await request(routes.createAssetBed, { + body: { + meta: { ...data, ...presetData.data }, + asset: assetId, + bed: bed?.id as string, + }, + }); if (res?.status === 201) { Notification.Success({ msg: "Preset Added Successfully", @@ -138,8 +134,10 @@ const ONVIFCamera = ({ assetId, facilityId, asset, onUpdated }: Props) => { } setLoadingAddPreset(false); }; + if (isLoading || loading || !facility) return ; - if (isLoading) return ; + const fallbackMiddleware = + asset?.location_object?.middleware_address || facilityMiddlewareHostname; return (
@@ -148,8 +146,26 @@ const ONVIFCamera = ({ assetId, facilityId, asset, onUpdated }: Props) => {
+

Middleware Hostname

+ {!middlewareHostname && ( +
+ + + Middleware hostname sourced from{" "} + {asset?.location_object?.middleware_address + ? "asset location" + : "asset facility"} + +
+ )} +
+ } + placeholder={fallbackMiddleware} value={middlewareHostname} onChange={({ value }) => setMiddlewareHostname(value)} /> diff --git a/src/Components/Assets/AssetTypes.tsx b/src/Components/Assets/AssetTypes.tsx index 52c7e45003c..8b96b6beeb7 100644 --- a/src/Components/Assets/AssetTypes.tsx +++ b/src/Components/Assets/AssetTypes.tsx @@ -91,6 +91,8 @@ export interface AssetData { }; } +export type AssetUpdate = Partial; + export interface AssetsResponse { count: number; next?: string; @@ -137,8 +139,12 @@ export interface AssetBedModel { created_date: string; modified_date: string; meta: Record; + asset?: string; + bed?: string; } +export type AssetBedBody = Partial; + export interface AssetServiceEdit { id: string; asset_service: AssetService; @@ -166,3 +172,9 @@ export interface PatientAssetBed { patient?: PatientModel; meta?: Record; } + +export interface AssetServiceUpdate { + external_id: string; + serviced_on: string; + note: string; +} diff --git a/src/Components/Assets/AssetsList.tsx b/src/Components/Assets/AssetsList.tsx index d91468166ac..593afdb137c 100644 --- a/src/Components/Assets/AssetsList.tsx +++ b/src/Components/Assets/AssetsList.tsx @@ -1,15 +1,8 @@ -import { useDispatch } from "react-redux"; import QrReader from "react-qr-reader"; -import { statusType, useAbortableEffect } from "../../Common/utils"; import * as Notification from "../../Utils/Notifications.js"; -import { - getAnyFacility, - listAssets, - getFacilityAssetLocation, - getAsset, -} from "../../Redux/actions"; +import { listAssets } from "../../Redux/actions"; import { assetClassProps, AssetData } from "./AssetTypes"; -import { useState, useCallback, useEffect, lazy } from "react"; +import { useState, useEffect, lazy } from "react"; import { Link, navigate } from "raviger"; import AssetFilter from "./AssetFilter"; import { parseQueryParams } from "../../Utils/primitives"; @@ -28,6 +21,9 @@ import AssetImportModal from "./AssetImportModal"; import Page from "../Common/components/Page"; import { AdvancedFilterButton } from "../../CAREUI/interactive/FiltersSlideover"; import { useTranslation } from "react-i18next"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; +import useQuery from "../../Utils/request/useQuery"; const Loading = lazy(() => import("../Common/Loading")); @@ -50,62 +46,45 @@ const AssetsList = () => { const [facility, setFacility] = useState(); const [asset_type, setAssetType] = useState(); const [status, setStatus] = useState(); - const [facilityName, setFacilityName] = useState(); const [asset_class, setAssetClass] = useState(); - const [locationName, setLocationName] = useState(); const [importAssetModalOpen, setImportAssetModalOpen] = useState(false); - const dispatch: any = useDispatch(); const assetsExist = assets.length > 0 && Object.keys(assets[0]).length > 0; const [showFacilityDialog, setShowFacilityDialog] = useState(false); const [selectedFacility, setSelectedFacility] = useState({ name: "", }); + const params = { + limit: resultsPerPage, + page: qParams.page, + offset: (qParams.page ? qParams.page - 1 : 0) * resultsPerPage, + search_text: qParams.search || "", + facility: qParams.facility || "", + asset_type: qParams.asset_type || "", + asset_class: qParams.asset_class || "", + location: qParams.facility ? qParams.location || "" : "", + status: qParams.status || "", + }; - const fetchData = useCallback( - async (status: statusType) => { - setIsLoading(true); - const params = { - limit: resultsPerPage, - page: qParams.page, - offset: (qParams.page ? qParams.page - 1 : 0) * resultsPerPage, - search_text: qParams.search || "", - facility: qParams.facility || "", - asset_type: qParams.asset_type || "", - asset_class: qParams.asset_class || "", - location: qParams.facility ? qParams.location || "" : "", - status: qParams.status || "", - }; - const { data } = await dispatch(listAssets(params)); - if (!status.aborted) { - setIsLoading(false); - if (!data) - Notification.Error({ - msg: "Something went wrong..!", - }); - else { - setAssets(data.results); - setTotalCount(data.count); - if (qParams.facility) { - const fetchFacility = await dispatch( - getAnyFacility(qParams.facility) - ); - setSelectedFacility(fetchFacility.data as FacilityModel); - } - } + useQuery(routes.listAssets, { + query: params, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { + setAssets(data.results); + setTotalCount(data.count); } }, - [ - resultsPerPage, - qParams.page, - qParams.search, - qParams.facility, - qParams.asset_type, - qParams.asset_class, - qParams.location, - qParams.status, - dispatch, - ] - ); + }); + + const { data: facilityObject } = useQuery(routes.getAnyFacility, { + pathParams: { id: qParams.facility }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { + setFacility(data); + setSelectedFacility(data); + } + }, + prefetch: !!qParams.facility, + }); useEffect(() => { setAssetType(qParams.asset_type); @@ -119,56 +98,13 @@ const AssetsList = () => { setAssetClass(qParams.asset_class); }, [qParams.asset_class]); - useAbortableEffect( - (status: statusType) => { - fetchData(status); - }, - [dispatch, fetchData] - ); - useEffect(() => { - async function fetchFacilityName() { - if (!qParams.facility) return setFacilityName(""); - const res = await dispatch(getAnyFacility(qParams.facility, "facility")); - setFacilityName(res?.data?.name); - } - fetchFacilityName(); - }, [dispatch, qParams.facility]); - - const fetchFacility = useCallback( - async (status: statusType) => { - if (!qParams.facility) return setFacility(undefined); - setIsLoading(true); - const res = await dispatch(getAnyFacility(qParams.facility)); - if (!status.aborted) { - setFacility(res?.data); - setIsLoading(false); - } - }, - [dispatch, qParams.facility] - ); - const fetchLocationName = useCallback( - async (status: statusType) => { - if (!qParams.location || !qParams.facility) - return setLocationName(undefined); - setIsLoading(true); - const res = await dispatch( - getFacilityAssetLocation(qParams.facility, qParams.location) - ); - if (!status.aborted) { - setLocationName(res?.data?.name); - setIsLoading(false); - } - }, - [dispatch, qParams.facility, qParams.location] - ); - - useAbortableEffect( - (status: statusType) => { - fetchFacility(status); - fetchLocationName(status); + const { data: locationObject } = useQuery(routes.getFacilityAssetLocation, { + pathParams: { + facility_external_id: String(qParams.facility), + external_id: String(qParams.location), }, - [fetchFacility, fetchLocationName] - ); + prefetch: !!(qParams.facility && qParams.location), + }); const getAssetIdFromQR = async (assetUrl: string) => { try { @@ -178,8 +114,10 @@ const AssetsList = () => { // QR Maybe searchParams "asset" or "assetQR" const assetId = params.asset || params.assetQR; if (assetId) { - const { data } = await dispatch(listAssets({ qr_code_id: assetId })); - return data.results[0].id; + const { data } = await request(routes.listAssets, { + query: { qr_code_id: assetId }, + }); + return data?.results[0].id; } } catch (err) { console.log(err); @@ -187,11 +125,13 @@ const AssetsList = () => { }; const checkValidAssetId = async (assetId: string) => { - const assetData = await dispatch(getAsset(assetId)); + const { data: assetData } = await request(routes.getAsset, { + pathParams: { id: assetId }, + }); try { - if (assetData.data) { + if (assetData) { navigate( - `/facility/${assetData.data.location_object.facility.id}/assets/${assetId}` + `/facility/${assetData.location_object.facility.id}/assets/${assetId}` ); } } catch (err) { @@ -288,6 +228,7 @@ const AssetsList = () => { ) : ( )} + {warrantyAmcValidityChip(asset.warranty_amc_end_of_validity)}
@@ -422,12 +363,30 @@ const AssetsList = () => { <> [ - value("Facility", "facility", facilityName ?? ""), + value( + "Facility", + "facility", + qParams.facility && facilityObject?.name + ), badge("Name/Serial No./QR ID", "search"), value("Asset Type", "asset_type", asset_type ?? ""), value("Asset Class", "asset_class", asset_class ?? ""), value("Status", "status", status?.replace(/_/g, " ") ?? ""), - value("Location", "location", locationName ?? ""), + value( + "Location", + "location", + qParams.location && locationObject?.name + ), + value( + "Warranty AMC End Of Validity Before", + "warranty_amc_end_of_validity_before", + qParams.warranty_amc_end_of_validity_before ?? "" + ), + value( + "Warranty AMC End Of Validity After", + "warranty_amc_end_of_validity_after", + qParams.warranty_amc_end_of_validity_after ?? "" + ), ]} />
@@ -484,4 +443,47 @@ const AssetsList = () => { ); }; +export const warrantyAmcValidityChip = ( + warranty_amc_end_of_validity: string +) => { + if (warranty_amc_end_of_validity === "" || !warranty_amc_end_of_validity) + return; + const today = new Date(); + const warrantyAmcEndDate = new Date(warranty_amc_end_of_validity); + + const days = Math.ceil( + Math.abs(Number(warrantyAmcEndDate) - Number(today)) / (1000 * 60 * 60 * 24) + ); + + if (warrantyAmcEndDate < today) { + return ( + + ); + } else if (days <= 30) { + return ( + + ); + } else if (days <= 90) { + return ( + + ); + } +}; + export default AssetsList; diff --git a/src/Components/Assets/configure/MonitorConfigure.tsx b/src/Components/Assets/configure/MonitorConfigure.tsx index 1d469335ce2..d1b24b24959 100644 --- a/src/Components/Assets/configure/MonitorConfigure.tsx +++ b/src/Components/Assets/configure/MonitorConfigure.tsx @@ -1,62 +1,50 @@ -import { Dispatch, useEffect, useState } from "react"; +import { useState } from "react"; import { BedSelect } from "../../Common/BedSelect"; import { BedModel } from "../../Facility/models"; import { AssetData } from "../AssetTypes"; -import { - createAssetBed, - listAssetBeds, - partialUpdateAssetBed, -} from "../../../Redux/actions"; import * as Notification from "../../../Utils/Notifications.js"; -import { useDispatch } from "react-redux"; import { Submit } from "../../Common/components/ButtonV2"; import { FieldLabel } from "../../Form/FormFields/FormField"; +import request from "../../../Utils/request/request"; +import routes from "../../../Redux/api"; +import useQuery from "../../../Utils/request/useQuery"; -const saveLink = (assetId: string, bedId: string, dispatch: Dispatch) => { - dispatch(createAssetBed({}, assetId, bedId)); +const saveLink = async (assetId: string, bedId: string) => { + await request(routes.createAssetBed, { + body: { + asset: assetId, + bed: bedId, + }, + }); Notification.Success({ msg: "AssetBed Link created successfully" }); }; -const update_Link = ( +const update_Link = async ( assetbedId: string, assetId: string, - bed: BedModel, - assetBed: any, - dispatch: Dispatch + bed: BedModel ) => { - dispatch( - partialUpdateAssetBed( - { - asset: assetId, - bed: bed.id, - }, - assetbedId - ) - ); + await request(routes.partialUpdateAssetBed, { + pathParams: { external_id: assetbedId }, + body: { + asset: assetId, + bed: bed.id ?? "", + }, + }); Notification.Success({ msg: "AssetBed Link updated successfully" }); }; export default function MonitorConfigure({ asset }: { asset: AssetData }) { const [bed, setBed] = useState({}); const [updateLink, setUpdateLink] = useState(false); - const [assetBed, setAssetBed] = useState(); - const dispatch: any = useDispatch(); - - const getAssetBeds = async (id: string) => { - const assetBeds = await dispatch(listAssetBeds({ asset: id })); - if (assetBeds.data?.results?.length > 0) { - setUpdateLink(true); - setAssetBed(assetBeds.data.results[0]); - setBed(assetBeds.data.results[0].bed_object); - } else { - setUpdateLink(false); - } - }; - - useEffect(() => { - if (asset.id) { - getAssetBeds(asset.id); - } - }, [asset]); + const { data: assetBed } = useQuery(routes.listAssetBeds, { + query: { asset: asset.id }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data && data.results.length > 0) { + setBed(data.results[0].bed_object); + setUpdateLink(true); + } + }, + }); return ( diff --git a/src/Components/Auth/Login.tsx b/src/Components/Auth/Login.tsx index cb7ea7f08f8..140a0013fd9 100644 --- a/src/Components/Auth/Login.tsx +++ b/src/Components/Auth/Login.tsx @@ -1,10 +1,9 @@ import { useEffect, useState } from "react"; -import { useDispatch } from "react-redux"; -import { postForgotPassword, postLogin } from "../../Redux/actions"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; import { useTranslation } from "react-i18next"; import ReCaptcha from "react-google-recaptcha"; import * as Notification from "../../Utils/Notifications.js"; -import { get } from "lodash"; import LegendInput from "../../CAREUI/interactive/LegendInput"; import LanguageSelectorLogin from "../Common/LanguageSelectorLogin"; import CareIcon from "../../CAREUI/icons/CareIcon"; @@ -25,7 +24,6 @@ export const Login = (props: { forgot?: boolean }) => { custom_logo_alt, custom_description, } = useConfig(); - const dispatch: any = useDispatch(); const initForm: any = { username: "", password: "", @@ -90,37 +88,35 @@ export const Login = (props: { forgot?: boolean }) => { }; }, []); - const handleSubmit = (e: any) => { + const handleSubmit = async (e: any) => { e.preventDefault(); const valid = validateData(); if (valid) { // replaces button with spinner setLoading(true); - dispatch(postLogin(valid)).then((resp: any) => { - const res = get(resp, "data", null); - const statusCode = get(resp, "status", ""); - if (res && statusCode === 429) { - setCaptcha(true); - // captcha displayed set back to login button - setLoading(false); - } else if (res && statusCode === 200) { - localStorage.setItem(LocalStorageKeys.accessToken, res.access); - localStorage.setItem(LocalStorageKeys.refreshToken, res.refresh); - - if ( - window.location.pathname === "/" || - window.location.pathname === "/login" - ) { - window.location.href = "/facility"; - } else { - window.location.href = window.location.pathname.toString(); - } + const { res, data } = await request(routes.login, { + body: { ...valid }, + }); + if (res && res.status === 429) { + setCaptcha(true); + // captcha displayed set back to login button + setLoading(false); + } else if (res && res.status === 200 && data) { + localStorage.setItem(LocalStorageKeys.accessToken, data.access); + localStorage.setItem(LocalStorageKeys.refreshToken, data.refresh); + if ( + window.location.pathname === "/" || + window.location.pathname === "/login" + ) { + window.location.href = "/facility"; } else { - // error from server set back to login button - setLoading(false); + window.location.href = window.location.pathname.toString(); } - }); + } else { + // error from server set back to login button + setLoading(false); + } } }; @@ -146,26 +142,22 @@ export const Login = (props: { forgot?: boolean }) => { return form; }; - const handleForgetSubmit = (e: any) => { + const handleForgetSubmit = async (e: any) => { e.preventDefault(); const valid = validateForgetData(); if (valid) { setLoading(true); - dispatch(postForgotPassword(valid)).then((resp: any) => { - setLoading(false); - const res = resp && resp.data; - if (res && res.status === "OK") { - Notification.Success({ - msg: t("password_sent"), - }); - } else if (res && res.data) { - setErrors(res.data); - } else { - Notification.Error({ - msg: t("something_wrong"), - }); - } + const { res, error } = await request(routes.forgotPassword, { + body: { ...valid }, }); + setLoading(false); + if (res?.ok) { + Notification.Success({ + msg: t("password_sent"), + }); + } else if (res && error) { + setErrors(error); + } } }; diff --git a/src/Components/Auth/ResetPassword.tsx b/src/Components/Auth/ResetPassword.tsx index 08dd1da44a0..47d120e1a97 100644 --- a/src/Components/Auth/ResetPassword.tsx +++ b/src/Components/Auth/ResetPassword.tsx @@ -1,7 +1,6 @@ import { useEffect, useState } from "react"; -import { useDispatch } from "react-redux"; +import request from "../../Utils/request/request.js"; import * as Notification from "../../Utils/Notifications.js"; -import { postResetPassword, checkResetToken } from "../../Redux/actions"; import { navigate } from "raviger"; import { useTranslation } from "react-i18next"; import { LocalStorageKeys } from "../../Common/constants"; @@ -9,9 +8,9 @@ import { Cancel, Submit } from "../Common/components/ButtonV2"; import TextFormField from "../Form/FormFields/TextFormField"; import { validateRule } from "../Users/UserAdd"; import { validatePassword } from "../../Common/validation.js"; +import routes from "../../Redux/api.js"; export const ResetPassword = (props: any) => { - const dispatch: any = useDispatch(); const initForm: any = { password: "", confirm: "", @@ -65,36 +64,37 @@ export const ResetPassword = (props: any) => { return form; }; - const handleSubmit = (e: any) => { + const handleSubmit = async (e: any) => { e.preventDefault(); const valid = validateData(); if (valid) { valid.token = props.token; - dispatch(postResetPassword(valid)).then((resp: any) => { - const res = resp && resp.data; - if (res && res.status === "OK") { - localStorage.removeItem(LocalStorageKeys.accessToken); - Notification.Success({ - msg: t("password_reset_success"), - }); - navigate("/login"); - } else if (res && res.data) { - setErrors(res.data); - } else { - Notification.Error({ - msg: t("password_reset_failure"), - }); - } + const { res, error } = await request(routes.resetPassword, { + body: { ...valid }, }); + if (res?.ok) { + localStorage.removeItem(LocalStorageKeys.accessToken); + Notification.Success({ + msg: t("password_reset_success"), + }); + navigate("/login"); + } else if (res && error) { + setErrors(error); + } } }; useEffect(() => { - if (props.token) { - dispatch(checkResetToken({ token: props.token })).then((resp: any) => { - const res = resp && resp.data; - if (!res || res.status !== "OK") navigate("/invalid-reset"); + const checkResetToken = async () => { + const { res } = await request(routes.checkResetToken, { + body: { token: props.token }, }); + if (!res || !res.ok) { + navigate("/invalid-reset"); + } + }; + if (props.token) { + checkResetToken(); } else { navigate("/invalid-reset"); } diff --git a/src/Components/Common/DateInputV2.tsx b/src/Components/Common/DateInputV2.tsx index bcebd4e0055..95652e68638 100644 --- a/src/Components/Common/DateInputV2.tsx +++ b/src/Components/Common/DateInputV2.tsx @@ -1,14 +1,4 @@ -import { MutableRefObject, useEffect, useRef, useState } from "react"; -import { - addMonths, - addYears, - format, - getDay, - getDaysInMonth, - isEqual, - subMonths, - subYears, -} from "date-fns"; +import { MutableRefObject, useEffect, useState } from "react"; import CareIcon from "../../CAREUI/icons/CareIcon"; import { Popover } from "@headlessui/react"; @@ -60,19 +50,24 @@ const DateInputV2: React.FC = ({ const [displayValue, setDisplayValue] = useState( value ? dayjs(value).format("DDMMYYYY") : "" ); - const popover = useRef(null); const decrement = () => { switch (type) { case "date": - setDatePickerHeaderDate((prev) => subMonths(prev, 1)); + setDatePickerHeaderDate((prev) => + dayjs(prev).subtract(1, "month").toDate() + ); break; case "month": - setDatePickerHeaderDate((prev) => subYears(prev, 1)); + setDatePickerHeaderDate((prev) => + dayjs(prev).subtract(1, "year").toDate() + ); break; case "year": - setDatePickerHeaderDate((prev) => subYears(prev, 1)); - setYear((prev) => subYears(prev, 10)); + setDatePickerHeaderDate((prev) => + dayjs(prev).subtract(1, "year").toDate() + ); + setYear((prev) => dayjs(prev).subtract(10, "year").toDate()); break; } }; @@ -80,24 +75,24 @@ const DateInputV2: React.FC = ({ const increment = () => { switch (type) { case "date": - setDatePickerHeaderDate((prev) => addMonths(prev, 1)); + setDatePickerHeaderDate((prev) => dayjs(prev).add(1, "month").toDate()); break; case "month": - setDatePickerHeaderDate((prev) => addYears(prev, 1)); + setDatePickerHeaderDate((prev) => dayjs(prev).add(1, "year").toDate()); break; case "year": - setDatePickerHeaderDate((prev) => addYears(prev, 1)); - setYear((prev) => addYears(prev, 10)); + setDatePickerHeaderDate((prev) => dayjs(prev).add(1, "year").toDate()); + setYear((prev) => dayjs(prev).add(10, "year").toDate()); break; } }; const isSelectedDate = (date: number) => { - if (value) - return isEqual( - new Date(value.getFullYear(), value.getMonth(), date), - value - ); + if (value) { + return dayjs( + new Date(value.getFullYear(), value.getMonth(), date) + ).isSame(dayjs(value)); + } }; type CloseFunction = ( @@ -114,12 +109,15 @@ const DateInputV2: React.FC = ({ ) ); close(); + setIsOpen?.(false); }; const getDayCount = (date: Date) => { - const daysInMonth = getDaysInMonth(date); + const daysInMonth = dayjs(date).daysInMonth(); - const dayOfWeek = getDay(new Date(date.getFullYear(), date.getMonth(), 1)); + const dayOfWeek = dayjs( + new Date(date.getFullYear(), date.getMonth(), 1) + ).day(); const blankDaysArray = []; for (let i = 1; i <= dayOfWeek; i++) { blankDaysArray.push(i); @@ -213,13 +211,7 @@ const DateInputV2: React.FC = ({ {({ open, close }) => (
- { - setIsOpen?.(!isOpen); - }} - > + = ({ {(open || isOpen) && ( { - setIsOpen?.(false); - }} - ref={popover} static className={classNames( "cui-dropdown-base absolute mt-0.5 w-72 divide-y-0 p-4", @@ -252,10 +240,6 @@ const DateInputV2: React.FC = ({ { - popover.current?.focus(); - e.preventDefault(); - }} className="cui-input-base bg-gray-50" value={ displayValue.replace( @@ -296,7 +280,7 @@ const DateInputV2: React.FC = ({ onClick={showMonthPicker} className="cursor-pointer rounded px-3 py-1 text-center font-medium text-black hover:bg-gray-300" > - {format(datePickerHeaderDate, "MMMM")} + {dayjs(datePickerHeaderDate).format("MMMM")}
)}
= ({

{type == "year" ? year.getFullYear() - : format(datePickerHeaderDate, "yyyy")} + : dayjs(datePickerHeaderDate).format("YYYY")}

@@ -385,14 +369,9 @@ const DateInputV2: React.FC = ({ )} onClick={setMonthValue(i)} > - {format( - new Date( - datePickerHeaderDate.getFullYear(), - i, - 1 - ), - "MMM" - )} + {dayjs( + new Date(datePickerHeaderDate.getFullYear(), i, 1) + ).format("MMM")}
))}
diff --git a/src/Components/Common/Export.tsx b/src/Components/Common/Export.tsx index 3595b3c84a0..f991c476aac 100644 --- a/src/Components/Common/Export.tsx +++ b/src/Components/Common/Export.tsx @@ -44,7 +44,7 @@ export const ExportMenu = ({ } + icon={} className="tooltip border-primary-500 bg-white text-primary-500 hover:bg-primary-100 enabled:border" > {exportItems.map((item) => ( diff --git a/src/Components/Common/GLocationPicker.tsx b/src/Components/Common/GLocationPicker.tsx index 5356d28fa2a..fc121b8519f 100644 --- a/src/Components/Common/GLocationPicker.tsx +++ b/src/Components/Common/GLocationPicker.tsx @@ -7,14 +7,6 @@ import CareIcon from "../../CAREUI/icons/CareIcon"; import useConfig from "../../Common/hooks/useConfig"; import { Popover } from "@headlessui/react"; -const render = (status: Status) => { - if (status === "LOADING") { - return ; - } - - return

{status}

; -}; - interface GLocationPickerProps { lat: number; lng: number; @@ -67,22 +59,37 @@ const GLocationPicker = ({ setCenter(m?.getCenter()?.toJSON()); }; + const render = (status: Status) => { + switch (status) { + case Status.LOADING: + return ; + case Status.SUCCESS: + return ( + + {location && } + + ); + default: + return

{status}

; + } + }; + return (
- - - {location && } - - +
); }; @@ -149,7 +156,9 @@ const Map: React.FC = ({ places.length > 0 && places[0].geometry?.location ) { - handleOnChange(places[0].geometry.location); + const selectedLocation = places[0].geometry.location; + handleOnChange(selectedLocation); + map?.setCenter(selectedLocation); } }); } diff --git a/src/Components/Common/Uptime.tsx b/src/Components/Common/Uptime.tsx index ce60e7b7f7e..6f6966b9053 100644 --- a/src/Components/Common/Uptime.tsx +++ b/src/Components/Common/Uptime.tsx @@ -4,7 +4,7 @@ import { listAssetAvailability } from "../../Redux/actions"; import { useDispatch } from "react-redux"; import * as Notification from "../../Utils/Notifications.js"; import { AssetStatus, AssetUptimeRecord } from "../Assets/AssetTypes"; -import { reverse } from "lodash"; +import { reverse } from "lodash-es"; import { classNames } from "../../Utils/utils"; import dayjs from "../../Utils/dayjs"; diff --git a/src/Components/Common/components/Menu.tsx b/src/Components/Common/components/Menu.tsx index 4b52a293f9e..49ee02b393e 100644 --- a/src/Components/Common/components/Menu.tsx +++ b/src/Components/Common/components/Menu.tsx @@ -16,6 +16,7 @@ interface DropdownMenuProps { children: JSX.Element | JSX.Element[]; disabled?: boolean | undefined; className?: string | undefined; + itemClassName?: string | undefined; } export default function DropdownMenu({ @@ -36,7 +37,9 @@ export default function DropdownMenu({ - + <>{props.children} diff --git a/src/Components/Common/components/SwitchTabs.tsx b/src/Components/Common/components/SwitchTabs.tsx index 0592f0272dd..047dba53b4b 100644 --- a/src/Components/Common/components/SwitchTabs.tsx +++ b/src/Components/Common/components/SwitchTabs.tsx @@ -1,36 +1,36 @@ export default function SwitchTabs(props: { - activeTab: boolean; + isTab2Active: boolean; onClickTab1: () => void; onClickTab2: () => void; - Tab1: string; - Tab2: string; + tab1: string; + tab2: string; }) { return (
- {props.Tab1} + {props.tab1}
- {props.Tab2} + {props.tab2}
); diff --git a/src/Components/CriticalCareRecording/NeurologicalMonitoring/CriticalCare__NeurologicalMonitoringEditor.res b/src/Components/CriticalCareRecording/NeurologicalMonitoring/CriticalCare__NeurologicalMonitoringEditor.res index 35d137e0414..dfe0e5cc3dc 100644 --- a/src/Components/CriticalCareRecording/NeurologicalMonitoring/CriticalCare__NeurologicalMonitoringEditor.res +++ b/src/Components/CriticalCareRecording/NeurologicalMonitoring/CriticalCare__NeurologicalMonitoringEditor.res @@ -68,12 +68,12 @@ let reducer = (state, action) => { | SetConsciousnessLevel(consciousnessLevel) => { ...state, dirty: true, - consciousnessLevel: consciousnessLevel, + consciousnessLevel, } | SetConsciousnessLevelDetails(consciousnessLevelDetails) => { ...state, dirty: true, - consciousnessLevelDetails: consciousnessLevelDetails, + consciousnessLevelDetails, } | SetLeftPupilSize(leftPupilSize) => { ...state, @@ -83,17 +83,17 @@ let reducer = (state, action) => { | SetLeftPupilSizeDetails(leftPupilSizeDetails) => { ...state, dirty: true, - leftPupilSizeDetails: leftPupilSizeDetails, + leftPupilSizeDetails, } | SetLeftPupilLightReaction(leftPupilLightReaction) => { ...state, dirty: true, - leftPupilLightReaction: leftPupilLightReaction, + leftPupilLightReaction, } | SetLeftPupilLightReactionDetails(leftPupilLightReactionDetails) => { ...state, dirty: true, - leftPupilLightReactionDetails: leftPupilLightReactionDetails, + leftPupilLightReactionDetails, } | SetRightPupilSize(rightPupilSize) => { ...state, @@ -103,17 +103,17 @@ let reducer = (state, action) => { | SetRightPupilSizeDetails(rightPupilSizeDetails) => { ...state, dirty: true, - rightPupilSizeDetails: rightPupilSizeDetails, + rightPupilSizeDetails, } | SetRightPupilLightReaction(rightPupilLightReaction) => { ...state, dirty: true, - rightPupilLightReaction: rightPupilLightReaction, + rightPupilLightReaction, } | SetRightPupilLightReactionDetails(rightPupilLightReactionDetails) => { ...state, dirty: true, - rightPupilLightReactionDetails: rightPupilLightReactionDetails, + rightPupilLightReactionDetails, } | SetGlasgowEyeOpen(glasgowEyeOpen) => {...state, glasgowEyeOpen: Some(glasgowEyeOpen)} | SetGlasgowVerbalResponse(glasgowVerbalResponse) => { @@ -129,22 +129,22 @@ let reducer = (state, action) => { | SetLimbResponseUpperExtremityRight(limbResponseUpperExtremityRight) => { ...state, dirty: true, - limbResponseUpperExtremityRight: limbResponseUpperExtremityRight, + limbResponseUpperExtremityRight, } | SetLimbResponseUpperExtremityLeft(limbResponseUpperExtremityLeft) => { ...state, dirty: true, - limbResponseUpperExtremityLeft: limbResponseUpperExtremityLeft, + limbResponseUpperExtremityLeft, } | SetLimbResponseLowerExtremityRight(limbResponseLowerExtremityRight) => { ...state, dirty: true, - limbResponseLowerExtremityRight: limbResponseLowerExtremityRight, + limbResponseLowerExtremityRight, } | SetLimbResponseLowerExtremityLeft(limbResponseLowerExtremityLeft) => { ...state, dirty: true, - limbResponseLowerExtremityLeft: limbResponseLowerExtremityLeft, + limbResponseLowerExtremityLeft, } | SetSaving => {...state, saving: true} @@ -265,7 +265,7 @@ let renderConsciousnessLevel = ( ) => {
{str("Level Of Consciousness")}
-
+
{Js.Array.map(consciousnessLevel => { onInputChange(consciousnessLevel)} /> - }, [Alert, Drowsy, Stuporous, Comatose, CannotBeAssessed])->React.array} + }, [ + Unresponsive, + Alert, + RespondsToPain, + RespondsToVoice, + AgitatedOrConfused, + OnsetOfAgitationAndConfusion, + ])->React.array}
- {ReactUtils.nullUnless( - onInputDetailsChange(event)} - />, - input === NeurologicalMonitoring.CannotBeAssessed, - )}
} diff --git a/src/Components/CriticalCareRecording/NeurologicalMonitoring/DailyRound__NeurologicalMonitoring.res b/src/Components/CriticalCareRecording/NeurologicalMonitoring/DailyRound__NeurologicalMonitoring.res index f476fd36c46..7dd295ecb51 100644 --- a/src/Components/CriticalCareRecording/NeurologicalMonitoring/DailyRound__NeurologicalMonitoring.res +++ b/src/Components/CriticalCareRecording/NeurologicalMonitoring/DailyRound__NeurologicalMonitoring.res @@ -16,10 +16,6 @@ let make = ( NeurologicalMonitoring.consciousnessLevel(neurologicalMonitoring), ), )} - {renderOptionalDescription( - "Consciousness Level Reaction Description", - NeurologicalMonitoring.consciousnessLevelDetails(neurologicalMonitoring), - )}
{title("Left Pupil")} diff --git a/src/Components/CriticalCareRecording/Pain/CriticalCare__PainInputModal.res b/src/Components/CriticalCareRecording/Pain/CriticalCare__PainInputModal.res index 63be6d2f3a4..eb4fd2b2376 100644 --- a/src/Components/CriticalCareRecording/Pain/CriticalCare__PainInputModal.res +++ b/src/Components/CriticalCareRecording/Pain/CriticalCare__PainInputModal.res @@ -31,7 +31,6 @@ let make = ( None }, [state]) - let handleClickOutside = %raw(` function (event, ref, hideModal) { if (ref.current && !ref.current.contains(event.target)) { @@ -56,18 +55,18 @@ let make = ( } }) -let getStatus = (min, minText, max, maxText, val) => { - switch (val >= min, val <= max) { - | (true, true) => ("Normal", "#059669") - | (true, false) => (maxText, "#DC2626") - | _ => (minText, "#DC2626") + let getStatus = (min, minText, max, maxText, val) => { + switch (val >= min, val <= max) { + | (true, true) => ("Normal", "#059669") + | (true, false) => (maxText, "#DC2626") + | _ => (minText, "#DC2626") + } } -}
@@ -173,7 +139,7 @@ export default function ResultList() { className="group inline-flex space-x-2 text-sm leading-5" >

- {result.name} - {result.age} {result.age_in} + {`${result.name}`} - {result.age} {result.age_in}

@@ -214,7 +180,7 @@ export default function ResultList() { }); } - if (isLoading || !data) { + if (loading) { manageResults = ( ); - } else if (data && data.length) { + } else if (data?.results.length) { manageResults = <>{resultList}; - } else if (data && data.length === 0) { + } else if (data?.results.length === 0) { manageResults = (
+ Serviced on @@ -537,7 +524,7 @@ const AssetManage = (props: AssetManageProps) => { Last Updated + Edit
Moved from + Moved to + Moved By + Moved On
@@ -222,9 +188,9 @@ export default function ResultList() {
@@ -286,8 +252,8 @@ export default function ResultList() {
@@ -358,7 +324,7 @@ export default function ResultList() {
- + import("../Common/Loading")); @@ -63,79 +57,76 @@ export default function UpdateResult(props: any) { const { id } = props; const { goBack } = useAppHistory(); - const dispatchAction: any = useDispatch(); const [state, dispatch] = useReducer(FormReducer, initialState); - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(true); const [isLocalbodyLoading, setIsLocalbodyLoading] = useState(false); const [isWardLoading, setIsWardLoading] = useState(false); const [localBody, setLocalBody] = useState(initialLocalbodies); const [ward, setWard] = useState(initialLocalbodies); - const fetchData = useCallback( - async (status: statusType) => { - setIsLoading(true); - const res = await dispatchAction(externalResult({ id: id })); - if (!status.aborted) { - if (res && res.data) { - const form = { ...state.form }; - form["name"] = res.data.name; - form["age"] = res.data.age; - form["age_in"] = res.data.age_in; - form["srf_id"] = res.data.srf_id; - form["address"] = res.data.address; - form["district"] = res.data.district_object.name; - form["local_body"] = String(res.data.local_body); - form["ward"] = String(res.data.ward); - form["patient_created"] = String(res.data.patient_created); + const { loading } = useQuery(routes.externalResult, { + pathParams: { id }, + onResponse: async ({ res, data }) => { + if (res && data) { + const form = { ...state.form }; + form["name"] = data.name; + form["age"] = data.age; + form["age_in"] = data.age_in; + form["srf_id"] = data.srf_id; + form["address"] = data.address; + form["district"] = data.district_object.name; + form["local_body"] = String(data.local_body); + form["ward"] = String(data.ward); + form["patient_created"] = String(data.patient_created); - dispatch({ type: "set_form", form }); + dispatch({ type: "set_form", form }); - Promise.all([ - fetchLocalBody(res.data.district), - fetchWards(res.data.local_body), - ]); - } + Promise.all([ + fetchLocalBody(data.district), + fetchWards(data.local_body), + ]); setIsLoading(false); } }, - [props.id, dispatchAction] - ); + }); - const fetchLocalBody = useCallback( - async (id: string) => { - if (Number(id) > 0) { - setIsLocalbodyLoading(true); - const localBodyList = await dispatchAction( - getLocalbodyByDistrict({ id }) - ); + const fetchLocalBody = async (id: number) => { + if (Number(id) > 0) { + setIsLocalbodyLoading(true); + const { res, data } = await request(routes.getLocalbodyByDistrict, { + pathParams: { id: String(id) }, + }); + if (res && data) { setIsLocalbodyLoading(false); - setLocalBody([...initialLocalbodies, ...localBodyList.data]); - } else { - setLocalBody(initialLocalbodies); + const transformedData = { + id: data.id, + name: data.name, + number: data.state, + }; + initialLocalbodies.push(transformedData); + setLocalBody([...initialLocalbodies]); } - }, - [dispatchAction] - ); + } else { + setLocalBody(initialLocalbodies); + } + }; const fetchWards = useCallback( - async (id: string) => { + async (id: number) => { if (Number(id) > 0) { setIsWardLoading(true); - const wardList = await dispatchAction(getWardByLocalBody({ id })); + const { res, data } = await request(routes.getWardByLocalBody, { + pathParams: { id: String(id) }, + }); + if (res && data) { + setWard([...initialWard, ...data.results]); + } setIsWardLoading(false); - setWard([...initialWard, ...wardList.data.results]); } else { setWard(initialLocalbodies); } }, - [dispatchAction] - ); - - useAbortableEffect( - (status: statusType) => { - fetchData(status); - }, - [fetchData] + [props.id] ); const validateForm = () => { @@ -195,15 +186,20 @@ export default function UpdateResult(props: any) { const validForm = validateForm(); if (validForm) { setIsLoading(true); - const data = { + const rdata = { address: state.form.address ? state.form.address : undefined, local_body: state.form.local_body ? state.form.local_body : undefined, ward: state.form.ward, patient_created: state.form.patient_created === "true", }; - const res = await dispatchAction(partialUpdateExternalResult(id, data)); + + const { res, data } = await request(routes.partialUpdateExternalResult, { + pathParams: { id }, + body: rdata, + }); + setIsLoading(false); - if (res && res.data) { + if (res && data) { dispatch({ type: "set_form", form: initForm }); Notification.Success({ msg: "External Result updated successfully", @@ -213,7 +209,7 @@ export default function UpdateResult(props: any) { } }; - if (isLoading) { + if (isLoading || loading) { return ; } @@ -262,10 +258,7 @@ export default function UpdateResult(props: any) { options={localBody} optionLabel={(localBody) => localBody.name} optionValue={(localBody) => localBody.id} - onChange={(e) => [ - handleChange(e), - fetchWards(String(e.value)), - ]} + onChange={(e) => [handleChange(e), fetchWards(e.value)]} error={state.errors.local_body} /> )} diff --git a/src/Components/ExternalResult/models.ts b/src/Components/ExternalResult/models.ts new file mode 100644 index 00000000000..8ccaba04d05 --- /dev/null +++ b/src/Components/ExternalResult/models.ts @@ -0,0 +1,72 @@ +export interface IExternalResultUploadCsv { + sample_tests: any[]; +} + +export interface IExternalResult { + id: number; + name: string; + age: number; + age_in: string; + test_type: string; + result: string; + result_date: string; + patient_created: boolean; + gender: string; + source: string; + is_repeat: boolean; + mobile_number: string; + patient_status: string; + sample_type: string; + sample_collection_date: string; + patient_category: string; + srf_id: string; + district_object: { + id: number; + name: string; + state: number; + }; + district: number; + ward: number; + local_body: number; + address: string; + ward_object: { + id: number; + number: number; + name: string; + }; + local_body_object: { + id: number; + name: string; + }; +} + +export interface ILocalBodies { + id: number; + name: string; + state: number; + number: number; + body_type: number; + localbody_code: string; + district: number; +} + +export interface IDeleteExternalResult { + detail: string; +} + +export interface IPartialUpdateExternalResult { + address: string; + ward: number; + local_body: number; + patient_created: boolean; +} + +export interface ILocalBodyByDistrict { + id: number; + name: string; + state: number; +} + +export interface IExternalResultCsv { + sample_tests: Partial[]; +} diff --git a/src/Components/Facility/AddLocationForm.tsx b/src/Components/Facility/AddLocationForm.tsx index f0dd7893aca..e71b68cc95c 100644 --- a/src/Components/Facility/AddLocationForm.tsx +++ b/src/Components/Facility/AddLocationForm.tsx @@ -25,12 +25,14 @@ export const AddLocationForm = (props: LocationFormProps) => { const dispatchAction: any = useDispatch(); const [isLoading, setIsLoading] = useState(false); const [name, setName] = useState(""); + const [middlewareAddress, setMiddlewareAddress] = useState(""); const [description, setDescription] = useState(""); const [facilityName, setFacilityName] = useState(""); const [locationName, setLocationName] = useState(""); const [errors, setErrors] = useState({ name: "", description: "", + middlewareAddress: "", }); const headerText = !locationId ? "Add Location" : "Update Location"; const buttonText = !locationId ? "Add Location" : "Update Location"; @@ -51,6 +53,7 @@ export const AddLocationForm = (props: LocationFormProps) => { setName(res?.data?.name || ""); setLocationName(res?.data?.name || ""); setDescription(res?.data?.description || ""); + setMiddlewareAddress(res?.data?.middleware_address || ""); } setIsLoading(false); } @@ -62,6 +65,7 @@ export const AddLocationForm = (props: LocationFormProps) => { const error = { name: "", description: "", + middlewareAddress: "", }; if (name.trim().length === 0) { @@ -69,6 +73,16 @@ export const AddLocationForm = (props: LocationFormProps) => { formValid = false; } + if ( + middlewareAddress && + middlewareAddress.match( + /^(?!https?:\/\/)[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)*\.[a-zA-Z]{2,}$/ + ) === null + ) { + error.middlewareAddress = "Invalid Middleware Address"; + formValid = false; + } + setErrors(error); return formValid; }; @@ -83,6 +97,7 @@ export const AddLocationForm = (props: LocationFormProps) => { const data = { name, description, + middleware_address: middlewareAddress, }; const res = await dispatchAction( @@ -157,8 +172,18 @@ export const AddLocationForm = (props: LocationFormProps) => { error={errors.description} />
+
+ setMiddlewareAddress(e.value)} + error={errors.middlewareAddress} + /> +
-
+
navigate(`/facility/${facilityId}/location`, { diff --git a/src/Components/Facility/AssetCreate.tsx b/src/Components/Facility/AssetCreate.tsx index 156d738857a..84fc09188d0 100644 --- a/src/Components/Facility/AssetCreate.tsx +++ b/src/Components/Facility/AssetCreate.tsx @@ -37,7 +37,8 @@ import useVisibility from "../../Utils/useVisibility"; import { validateEmailAddress } from "../../Common/validation"; import { dateQueryString, parsePhoneNumber } from "../../Utils/utils.js"; import dayjs from "../../Utils/dayjs"; -import DateInputV2 from "../Common/DateInputV2.js"; +import DateFormField from "../Form/FormFields/DateFormField.js"; +import { t } from "i18next"; const Loading = lazy(() => import("../Common/Loading")); @@ -305,7 +306,7 @@ const AssetCreate = (props: AssetProps) => { setLocation(""); setAssetType(assetTypeInitial); setAssetClass(assetClassInitial); - setIsWorking(""); + setIsWorking(undefined); setNotWorkingReason(""); setSerialNumber(""); setVendorName(""); @@ -404,7 +405,7 @@ const AssetCreate = (props: AssetProps) => { if (locations.length === 0) { return ( {

- You need at least a location to create an assest. + {t("you_need_at_least_a_location_to_create_an_assest")}

@@ -440,7 +441,8 @@ const AssetCreate = (props: AssetProps) => { onClick={() => setIsScannerActive(false)} className="btn btn-default mb-2" > - Close Scanner + + {t("close_scanner")} { } style={{ width: "100%" }} /> -

Scan Asset QR!

+

+ {t("scan_asset_qr")} +

); @@ -479,7 +483,7 @@ const AssetCreate = (props: AssetProps) => { return (
{ > setName(value)} @@ -544,7 +548,7 @@ const AssetCreate = (props: AssetProps) => { {/* Location */} - Asset Location + {t("asset_location")}
{ data-testid="asset-type-input" > { { > setDescription(value)} error={state.errors.description} @@ -664,7 +668,7 @@ const AssetCreate = (props: AssetProps) => { className="col-span-6" required name="is_working" - label="Working Status" + label={t("working_status")} options={["true", "false"]} optionLabel={(option) => { return ( @@ -692,8 +696,8 @@ const AssetCreate = (props: AssetProps) => { > setNotWorkingReason(e.value)} error={state.errors.not_working_reason} @@ -717,7 +721,7 @@ const AssetCreate = (props: AssetProps) => { id="qr_code_id" name="qr_code_id" placeholder="" - label="Asset QR ID" + label={t("asset_qr_id")} value={qrCodeId} onChange={(e) => setQrCodeId(e.value)} error={state.errors.qr_code_id} @@ -743,9 +747,9 @@ const AssetCreate = (props: AssetProps) => { setManufacturer(e.value)} error={state.errors.manufacturer} /> @@ -760,7 +764,7 @@ const AssetCreate = (props: AssetProps) => { { const value = dayjs(event.value); @@ -788,8 +792,8 @@ const AssetCreate = (props: AssetProps) => { setSupportName(e.value)} error={state.errors.support_name} @@ -804,7 +808,7 @@ const AssetCreate = (props: AssetProps) => { > setSupportPhone(e.value)} @@ -822,8 +826,8 @@ const AssetCreate = (props: AssetProps) => { setSupportEmail(e.value)} error={state.errors.support_email} @@ -841,9 +845,9 @@ const AssetCreate = (props: AssetProps) => { setVendorName(e.value)} error={state.errors.vendor_name} /> @@ -858,7 +862,7 @@ const AssetCreate = (props: AssetProps) => { setSerialNumber(e.value)} error={state.errors.serial_number} @@ -874,25 +878,26 @@ const AssetCreate = (props: AssetProps) => { ref={fieldRef["last_serviced_on"]} data-testid="asset-last-serviced-on-input" > - Last Serviced On - { if ( - dayjs(date).format("YYYY-MM-DD") > + dayjs(date.value).format("YYYY-MM-DD") > new Date().toLocaleDateString("en-ca") ) { Notification.Error({ msg: "Last Serviced date can't be in future", }); } else { - setLastServicedOn(dayjs(date).format("YYYY-MM-DD")); + setLastServicedOn( + dayjs(date.value).format("YYYY-MM-DD") + ); } }} - max={new Date()} /> { > setNotes(e.value)} error={state.errors.notes} @@ -928,13 +935,13 @@ const AssetCreate = (props: AssetProps) => { /> handleSubmit(e, false)} - label={assetId ? "Update" : "Create Asset"} + label={assetId ? t("update") : t("create_asset")} /> {!assetId && ( handleSubmit(e, true)} - label="Create & Add More" + label={t("create_add_more")} /> )}
diff --git a/src/Components/Facility/ConsultationCard.tsx b/src/Components/Facility/ConsultationCard.tsx index f6b4484b477..4859b981e8f 100644 --- a/src/Components/Facility/ConsultationCard.tsx +++ b/src/Components/Facility/ConsultationCard.tsx @@ -131,6 +131,7 @@ export const ConsultationCard = (props: ConsultationProps) => {
navigate( diff --git a/src/Components/Facility/ConsultationDetails/ConsultationMedicinesTab.tsx b/src/Components/Facility/ConsultationDetails/ConsultationMedicinesTab.tsx index 19810102833..0643765339f 100644 --- a/src/Components/Facility/ConsultationDetails/ConsultationMedicinesTab.tsx +++ b/src/Components/Facility/ConsultationDetails/ConsultationMedicinesTab.tsx @@ -1,9 +1,12 @@ import { ConsultationTabProps } from "./index"; import PrescriptionAdministrationsTable from "../../Medicine/PrescriptionAdministrationsTable"; +import PageTitle from "../../Common/PageHeadTitle"; export const ConsultationMedicinesTab = (props: ConsultationTabProps) => { return (
+ {/* eslint-disable-next-line i18next/no-literal-string */} + import("../../Common/PageTitle")); -export const ConsultationNeutritionTab = (props: ConsultationTabProps) => { +export const ConsultationNutritionTab = (props: ConsultationTabProps) => { return (
diff --git a/src/Components/Facility/ConsultationDetails/index.tsx b/src/Components/Facility/ConsultationDetails/index.tsx index 403f1752704..cedb1a843d3 100644 --- a/src/Components/Facility/ConsultationDetails/index.tsx +++ b/src/Components/Facility/ConsultationDetails/index.tsx @@ -41,6 +41,7 @@ import { ConsultationVentilatorTab } from "./ConsultationVentilatorTab"; import { ConsultationPressureSoreTab } from "./ConsultationPressureSoreTab"; import { ConsultationDialysisTab } from "./ConsultationDialysisTab"; import { ConsultationNeurologicalMonitoringTab } from "./ConsultationNeurologicalMonitoringTab"; +import { ConsultationNutritionTab } from "./ConsultationNutritionTab"; const Loading = lazy(() => import("../../Common/Loading")); const PageTitle = lazy(() => import("../../Common/PageTitle")); @@ -65,7 +66,7 @@ const TABS = { NURSING: ConsultationNursingTab, NEUROLOGICAL_MONITORING: ConsultationNeurologicalMonitoringTab, VENTILATOR: ConsultationVentilatorTab, - NUTRITION: ConsultationNursingTab, + NUTRITION: ConsultationNutritionTab, PRESSURE_SORE: ConsultationPressureSoreTab, DIALYSIS: ConsultationDialysisTab, }; @@ -308,6 +309,7 @@ export const ConsultationDetails = (props: any) => { ) : ( navigate( `/facility/${patientData.facility}/patient/${patientData.id}/shift/new` @@ -351,6 +353,7 @@ export const ConsultationDetails = (props: any) => { Patient Details @@ -449,6 +452,7 @@ export const ConsultationDetails = (props: any) => { setOpenDischargeDialog(true)} disabled={!!consultationData.discharge_date} > @@ -495,14 +499,20 @@ export const ConsultationDetails = (props: any) => {
-
)} diff --git a/src/Components/Facility/Consultations/LiveFeed.tsx b/src/Components/Facility/Consultations/LiveFeed.tsx index c6ba749b471..aba473e958d 100644 --- a/src/Components/Facility/Consultations/LiveFeed.tsx +++ b/src/Components/Facility/Consultations/LiveFeed.tsx @@ -36,6 +36,7 @@ const LiveFeed = (props: any) => { const [streamStatus, setStreamStatus] = useState( StreamStatus.Offline ); + const [videoStartTime, setVideoStartTime] = useState(null); const [bed, setBed] = useState({}); const [preset, setNewPreset] = useState(""); const [loading, setLoading] = useState(); @@ -100,6 +101,16 @@ const LiveFeed = (props: any) => { }, }); + const calculateVideoLiveDelay = () => { + const video = liveFeedPlayerRef.current as HTMLVideoElement; + if (!video || !videoStartTime) return 0; + + const timeDifference = + (new Date().getTime() - videoStartTime.getTime()) / 1000; + + return timeDifference - video.currentTime; + }; + const getBedPresets = async (id: any) => { const bedAssets = await dispatch( listAssetBeds({ @@ -223,6 +234,7 @@ const LiveFeed = (props: any) => { }, reset: () => { setStreamStatus(StreamStatus.Loading); + setVideoStartTime(null); startStream({ onSuccess: () => setStreamStatus(StreamStatus.Playing), onError: () => setStreamStatus(StreamStatus.Offline), @@ -344,8 +356,25 @@ const LiveFeed = (props: any) => { playsInline className="z-10 h-full w-full" ref={liveFeedPlayerRef} + onPlay={() => { + setVideoStartTime(() => new Date()); + }} + onWaiting={() => { + const delay = calculateVideoLiveDelay(); + if (delay > 5) { + setStreamStatus(StreamStatus.Loading); + } + }} > + {streamStatus === StreamStatus.Playing && + calculateVideoLiveDelay() > 3 && ( +
+ + Slow Network Detected +
+ )} + {loading && (
diff --git a/src/Components/Facility/Consultations/NeurologicalTables.tsx b/src/Components/Facility/Consultations/NeurologicalTables.tsx index 89e9d598604..36fae175480 100644 --- a/src/Components/Facility/Consultations/NeurologicalTables.tsx +++ b/src/Components/Facility/Consultations/NeurologicalTables.tsx @@ -28,10 +28,7 @@ const DataTable = (props: any) => { Right
-
+
{data.map((x: any, i: any) => { return (
{ const LOC_OPTIONS = [ { id: 0, value: "Unknown" }, { id: 5, value: "Alert" }, - { id: 10, value: "Drowsy" }, - { id: 15, value: "Stuporous" }, - { id: 20, value: "Comatose" }, - { id: 25, value: "Cannot Be Assessed" }, + { id: 10, value: "Responds to Voice" }, + { id: 15, value: "Responds to Pain" }, + { id: 20, value: "Unresponsive" }, + { id: 25, value: "Agitated or Confused" }, + { id: 30, value: "Onset of Agitation and Confusion" }, ]; const REACTION_OPTIONS = [ @@ -297,16 +295,13 @@ export const NeurologicalTable = (props: any) => {
Level Of Consciousness
-
+
{locData.map((x: any, i: any) => (
-
+
{x.date}
@@ -376,10 +371,7 @@ export const NeurologicalTable = (props: any) => { Total
-
+
{glasgowData.map((x: any, i: any) => { return (
{ const { @@ -197,7 +225,8 @@ export const LinePlot = (props: any) => { } return ( - { @@ -81,5 +108,5 @@ export const StackedLinePlot = (props: any) => { }, series: series, }; - return ; + return ; }; diff --git a/src/Components/Facility/FacilityCard.tsx b/src/Components/Facility/FacilityCard.tsx index 9fc80f7d211..2689193b4c2 100644 --- a/src/Components/Facility/FacilityCard.tsx +++ b/src/Components/Facility/FacilityCard.tsx @@ -47,11 +47,11 @@ export const FacilityCard = (props: { facility: any; userType: any }) => { return (
-
+
{(facility.read_cover_image_url && ( {
{(facility.read_cover_image_url && ( { )} -
+
{facility.kasp_empanelled && ( @@ -87,7 +87,7 @@ export const FacilityCard = (props: { facility: any; userType: any }) => { {kasp_string}
)} -
+
{
-
+
-
+
0.85 @@ -219,7 +219,7 @@ export const FacilityCard = (props: { facility: any; userType: any }) => {
-
+
{userType !== "Staff" ? ( import("../Common/Loading")); const initForm = { @@ -18,6 +19,7 @@ const initForm = { ward: 0, middleware_address: "", }; + const initialState = { form: { ...initForm }, errors: {}, @@ -42,42 +44,33 @@ const FormReducer = (state = initialState, action: any) => { } }; -export const UpdateFacilityMiddleware = (props: any) => { +interface IProps { + facilityId: string; +} + +export const FacilityConfigure = (props: IProps) => { const [state, dispatch] = useReducer(FormReducer, initialState); const { facilityId } = props; const [isLoading, setIsLoading] = useState(false); - const { res, data, refetch } = useQuery(routes.getPermittedFacility, { - pathParams: { - id: facilityId, - }, - }); - - useEffect(() => { - if (facilityId) { - setIsLoading(true); - if (data) { + const { loading } = useQuery(routes.getPermittedFacility, { + pathParams: { id: facilityId }, + onResponse: (res) => { + if (res.data) { const formData = { - name: data.name, - state: data.state, - district: data.district, - local_body: data.local_body, - ward: data.ward, - middleware_address: data.middleware_address, + name: res.data.name, + state: res.data.state, + district: res.data.district, + local_body: res.data.local_body, + ward: res.data.ward, + middleware_address: res.data.middleware_address, }; dispatch({ type: "set_form", form: formData }); - } else { - navigate(`/facility/${facilityId}`); } - setIsLoading(false); - } - }, [facilityId, res, data]); - - useEffect(() => { - refetch(); - }, [dispatch, refetch]); + }, + }); - const handleSubmit = async (e: any) => { + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setIsLoading(true); if (!state.form.middleware_address) { @@ -102,44 +95,39 @@ export const UpdateFacilityMiddleware = (props: any) => { setIsLoading(false); return; } - const data: any = { + + const data = { ...state.form, middleware_address: state.form.middleware_address, }; - // data for request body is not same - keep any - const { res, data: updateData } = await request( - routes.partialUpdateFacility, - { - body: data, - pathParams: { - id: facilityId, - }, - } - ); + const { res, error } = await request(routes.partialUpdateFacility, { + pathParams: { id: facilityId }, + body: data, + }); + setIsLoading(false); - if (res && updateData) { + if (res?.ok) { Notification.Success({ msg: "Facility updated successfully", }); navigate(`/facility/${facilityId}`); } else { - if (updateData) - Notification.Error({ - msg: "Something went wrong: ", // No detail property in response - }); + Notification.Error({ + msg: error?.detail ?? "Something went wrong", + }); } setIsLoading(false); }; - const handleChange = (e: any) => { + const handleChange = (e: FieldChangeEvent) => { dispatch({ type: "set_form", form: { ...state.form, [e.name]: e.value }, }); }; - if (isLoading) { + if (isLoading || loading) { return ; } @@ -149,22 +137,23 @@ export const UpdateFacilityMiddleware = (props: any) => { crumbsReplacements={{ [facilityId]: { name: state.form.name }, }} - className="mx-auto max-w-3xl" + className="w-full overflow-x-hidden" >
-
handleSubmit(e)}> +
handleChange(e)} + onChange={handleChange} error={state.errors?.middleware_address} />
-
+
navigate(`/facility/${facilityId}`)} />
diff --git a/src/Components/Facility/FacilityHome.tsx b/src/Components/Facility/FacilityHome.tsx index d98c5f3a3b9..87ba421632f 100644 --- a/src/Components/Facility/FacilityHome.tsx +++ b/src/Components/Facility/FacilityHome.tsx @@ -412,7 +412,7 @@ export const FacilityHome = (props: any) => { StaffUserTypeIndex; const editCoverImageTooltip = hasPermissionToEditCoverImage && ( -
+
{`${hasCoverImage ? "Edit" : "Upload"}`}
@@ -630,9 +630,7 @@ export const FacilityHome = (props: any) => { - navigate(`/facility/${facilityId}/middleware/update`) - } + onClick={() => navigate(`/facility/${facilityId}/configure`)} authorizeFor={NonReadOnlyUsers} icon={} > diff --git a/src/Components/Facility/FacilityUsers.tsx b/src/Components/Facility/FacilityUsers.tsx index 51da42b3337..712ef98312a 100644 --- a/src/Components/Facility/FacilityUsers.tsx +++ b/src/Components/Facility/FacilityUsers.tsx @@ -312,7 +312,10 @@ export default function FacilityUsers(props: any) {
{user.username && ( -
+
{user.username}
)} diff --git a/src/Components/Facility/Investigations/InvestigationTable.tsx b/src/Components/Facility/Investigations/InvestigationTable.tsx index 8149e18496b..54e7e50bdc7 100644 --- a/src/Components/Facility/Investigations/InvestigationTable.tsx +++ b/src/Components/Facility/Investigations/InvestigationTable.tsx @@ -2,7 +2,6 @@ import ButtonV2 from "../../Common/components/ButtonV2"; import CareIcon from "../../../CAREUI/icons/CareIcon"; import { SelectFormField } from "../../Form/FormFields/SelectFormField"; import TextFormField from "../../Form/FormFields/TextFormField"; -import _ from "lodash"; import { classNames } from "../../../Utils/utils"; import { useState } from "react"; diff --git a/src/Components/Facility/Investigations/Reports/index.tsx b/src/Components/Facility/Investigations/Reports/index.tsx index ab5380c62ca..9b3c29d40f8 100644 --- a/src/Components/Facility/Investigations/Reports/index.tsx +++ b/src/Components/Facility/Investigations/Reports/index.tsx @@ -1,5 +1,5 @@ import * as Notification from "../../../../Utils/Notifications"; - +import _ from "lodash-es"; import { Group, InvestigationType } from ".."; import { getPatient, @@ -17,7 +17,6 @@ import { InvestigationResponse } from "./types"; import Loading from "../../../Common/Loading"; import Page from "../../../Common/components/Page"; import ReportTable from "./ReportTable"; -import _ from "lodash"; import { useDispatch } from "react-redux"; import { useRef } from "react"; diff --git a/src/Components/Facility/Investigations/Reports/utils.tsx b/src/Components/Facility/Investigations/Reports/utils.tsx index 485a3e1d5f4..e57f3c42c53 100644 --- a/src/Components/Facility/Investigations/Reports/utils.tsx +++ b/src/Components/Facility/Investigations/Reports/utils.tsx @@ -1,4 +1,4 @@ -import _ from "lodash"; +import _ from "lodash-es"; import { InvestigationResponse } from "./types"; export const transformData = _.memoize((data: InvestigationResponse) => { diff --git a/src/Components/Facility/Investigations/ShowInvestigation.tsx b/src/Components/Facility/Investigations/ShowInvestigation.tsx index 4c2826f6eea..00196bb6678 100644 --- a/src/Components/Facility/Investigations/ShowInvestigation.tsx +++ b/src/Components/Facility/Investigations/ShowInvestigation.tsx @@ -8,8 +8,8 @@ import { } from "../../../Redux/actions"; import PageTitle from "../../Common/PageTitle"; import InvestigationTable from "./InvestigationTable"; - -import _ from "lodash"; +import _ from "lodash-es"; +import { set } from "lodash-es"; import { navigate } from "raviger"; import * as Notification from "../../../Utils/Notifications.js"; @@ -110,7 +110,7 @@ export default function ShowInvestigation(props: any) { const handleValueChange = (value: any, name: string) => { const changedFields = { ...state.changedFields }; - _.set(changedFields, name, value); + set(changedFields, name, value); dispatch({ type: "set_changed_fields", changedFields }); }; diff --git a/src/Components/Facility/Investigations/Table.tsx b/src/Components/Facility/Investigations/Table.tsx index 4d6ce4c2340..4bd7e841543 100644 --- a/src/Components/Facility/Investigations/Table.tsx +++ b/src/Components/Facility/Investigations/Table.tsx @@ -1,7 +1,7 @@ import { FieldChangeEvent } from "../../Form/FormFields/Utils"; import { SelectFormField } from "../../Form/FormFields/SelectFormField"; import TextFormField from "../../Form/FormFields/TextFormField"; -import _ from "lodash"; +import { set } from "lodash-es"; import { useState } from "react"; const TestRow = ({ data, value, onChange, i }: any) => { @@ -59,7 +59,7 @@ export const TestTable = ({ title, data, state, dispatch }: any) => { const handleValueChange = (value: any, name: string) => { const form = { ...state }; - _.set(form, name, value); + set(form, name, value); dispatch({ type: "set_form", form }); }; diff --git a/src/Components/Facility/LegacyFacilityCNS.tsx b/src/Components/Facility/LegacyFacilityCNS.tsx index 457ae172983..c994c028614 100644 --- a/src/Components/Facility/LegacyFacilityCNS.tsx +++ b/src/Components/Facility/LegacyFacilityCNS.tsx @@ -10,7 +10,7 @@ import Pagination from "../Common/Pagination"; import { PatientModel } from "../Patient/models"; import { FacilityModel } from "./models"; import AutocompleteFormField from "../Form/FormFields/Autocomplete"; -import { uniqBy } from "lodash"; +import { uniqBy } from "lodash-es"; import DialogModal from "../Common/Dialog"; import { LegacyMonitorCard } from "./LegacyMonitorCard"; import request from "../../Utils/request/request"; diff --git a/src/Components/Facility/LocationManagement.tsx b/src/Components/Facility/LocationManagement.tsx index 38dcfc1f389..c018a7c222b 100644 --- a/src/Components/Facility/LocationManagement.tsx +++ b/src/Components/Facility/LocationManagement.tsx @@ -65,12 +65,24 @@ export default function LocationManagement({ facilityId }: Props) { ); } -const Location = ({ name, description, id }: LocationModel) => ( +const Location = ({ + name, + description, + middleware_address, + id, +}: LocationModel) => (
-
-

{name}

-

{description}

+
+

+ {name} +

+ {description || "-"} +

+

+

+ {middleware_address} +

diff --git a/src/Components/Facility/models.tsx b/src/Components/Facility/models.tsx index d1bc96144d7..0f375871259 100644 --- a/src/Components/Facility/models.tsx +++ b/src/Components/Facility/models.tsx @@ -33,7 +33,6 @@ export interface HomeFacilityModel { export interface FacilityModel { id?: number; name?: string; - district?: number; read_cover_image_url?: string; facility_type?: string; address?: string; @@ -58,6 +57,10 @@ export interface FacilityModel { ward_object?: WardModel; modified_date?: string; created_date?: string; + state: number; + district: number; + local_body: number; + ward: number; } export interface CapacityModal { @@ -148,6 +151,7 @@ export type ConsultationModel = { death_datetime?: string; death_confirmed_doctor?: string; is_readmission?: boolean; + medico_legal_case?: boolean; }; export interface PatientStatsModel { id?: number; @@ -183,6 +187,7 @@ export interface LocationModel { id?: string; name?: string; description?: string; + middleware_address?: string; facility?: { name: string; }; diff --git a/src/Components/Form/AutoCompleteAsync.tsx b/src/Components/Form/AutoCompleteAsync.tsx index 5f33c6388c5..db2d1e888df 100644 --- a/src/Components/Form/AutoCompleteAsync.tsx +++ b/src/Components/Form/AutoCompleteAsync.tsx @@ -1,6 +1,6 @@ import { useEffect, useState, useMemo } from "react"; import { Combobox } from "@headlessui/react"; -import { debounce } from "lodash"; +import { debounce } from "lodash-es"; import { DropdownTransition } from "../Common/components/HelperComponents"; import CareIcon from "../../CAREUI/icons/CareIcon"; import { diff --git a/src/Components/Form/Form.tsx b/src/Components/Form/Form.tsx index 5b1cf018965..66383616034 100644 --- a/src/Components/Form/Form.tsx +++ b/src/Components/Form/Form.tsx @@ -1,4 +1,4 @@ -import { isEmpty, omitBy } from "lodash"; +import { isEmpty, omitBy } from "lodash-es"; import { useEffect, useMemo, useState } from "react"; import { classNames } from "../../Utils/utils"; import { Cancel, Submit } from "../Common/components/ButtonV2"; @@ -7,6 +7,7 @@ import { FormContextValue, createFormContext } from "./FormContext"; import { FieldChangeEvent } from "./FormFields/Utils"; import { FormDetails, FormErrors, FormState, formReducer } from "./Utils"; import { DraftSection, useAutoSaveReducer } from "../../Utils/AutoSave"; +import * as Notification from "../../Utils/Notifications"; type Props = { className?: string; @@ -51,6 +52,10 @@ const Form = ({ if (Object.keys(errors).length) { dispatch({ type: "set_errors", errors }); + + if (errors.$all) { + Notification.Error({ msg: errors.$all }); + } return; } } diff --git a/src/Components/Form/FormFields/NumericWithUnitsFormField.tsx b/src/Components/Form/FormFields/NumericWithUnitsFormField.tsx index 31ac781e018..02aa03fdf71 100644 --- a/src/Components/Form/FormFields/NumericWithUnitsFormField.tsx +++ b/src/Components/Form/FormFields/NumericWithUnitsFormField.tsx @@ -34,6 +34,7 @@ export default function NumericWithUnitsFormField(props: Props) { max={props.max} autoComplete={props.autoComplete} required={field.required} + value={numValue} onChange={(e) => field.handleChange(e.target.value + " " + unitValue)} />
diff --git a/src/Components/Form/Utils.ts b/src/Components/Form/Utils.ts index 2ec5d4b60e5..0592e81a06c 100644 --- a/src/Components/Form/Utils.ts +++ b/src/Components/Form/Utils.ts @@ -1,7 +1,9 @@ import { FieldError } from "./FieldValidators"; export type FormDetails = { [key: string]: any }; -export type FormErrors = Partial>; +export type FormErrors = Partial< + Record +>; export type FormState = { form: T; errors: FormErrors }; export type FormAction = | { type: "set_form"; form: T } diff --git a/src/Components/Medicine/CreatePrescriptionForm.tsx b/src/Components/Medicine/CreatePrescriptionForm.tsx index fb7fec5f431..2a58c632d20 100644 --- a/src/Components/Medicine/CreatePrescriptionForm.tsx +++ b/src/Components/Medicine/CreatePrescriptionForm.tsx @@ -1,4 +1,4 @@ -import { FieldError, RequiredFieldValidator } from "../Form/FieldValidators"; +import { RequiredFieldValidator } from "../Form/FieldValidators"; import Form from "../Form/Form"; import { SelectFormField } from "../Form/FormFields/SelectFormField"; import TextAreaFormField from "../Form/FormFields/TextAreaFormField"; @@ -11,6 +11,7 @@ import NumericWithUnitsFormField from "../Form/FormFields/NumericWithUnitsFormFi import { useTranslation } from "react-i18next"; import MedibaseAutocompleteFormField from "./MedibaseAutocompleteFormField"; import dayjs from "../../Utils/dayjs"; +import { PrescriptionFormValidator } from "./validators"; export default function CreatePrescriptionForm(props: { prescription: Prescription; @@ -40,16 +41,7 @@ export default function CreatePrescriptionForm(props: { } }} noPadding - validate={(form) => { - const errors: Partial> = {}; - errors.medicine_object = RequiredFieldValidator()(form.medicine_object); - errors.dosage = RequiredFieldValidator()(form.dosage); - if (form.is_prn) - errors.indicator = RequiredFieldValidator()(form.indicator); - if (!form.is_prn) - errors.frequency = RequiredFieldValidator()(form.frequency); - return errors; - }} + validate={PrescriptionFormValidator()} className="max-w-3xl" > {(field) => ( diff --git a/src/Components/Medicine/EditPrescriptionForm.tsx b/src/Components/Medicine/EditPrescriptionForm.tsx new file mode 100644 index 00000000000..d5261f70c7e --- /dev/null +++ b/src/Components/Medicine/EditPrescriptionForm.tsx @@ -0,0 +1,158 @@ +import { useState } from "react"; +import Form from "../Form/Form"; +import { Prescription } from "./models"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; +import * as Notification from "../../Utils/Notifications"; +import useSlug from "../../Common/hooks/useSlug"; +import { RequiredFieldValidator } from "../Form/FieldValidators"; +import { useTranslation } from "react-i18next"; +import { SelectFormField } from "../Form/FormFields/SelectFormField"; +import NumericWithUnitsFormField from "../Form/FormFields/NumericWithUnitsFormField"; +import { + PRESCRIPTION_FREQUENCIES, + PRESCRIPTION_ROUTES, +} from "./CreatePrescriptionForm"; +import TextFormField from "../Form/FormFields/TextFormField"; +import TextAreaFormField from "../Form/FormFields/TextAreaFormField"; +import { EditPrescriptionFormValidator } from "./validators"; + +interface Props { + initial: Prescription; + onDone: (created: boolean) => void; +} + +const handleSubmit = async ( + consultation_external_id: string, + oldObj: Prescription, + { discontinued_reason, ...newObj }: Prescription +) => { + const discontinue = await request(routes.discontinuePrescription, { + pathParams: { consultation_external_id, external_id: oldObj.id }, + body: { + discontinued_reason: discontinued_reason + ? `Edit: ${discontinued_reason}` + : "Edited", + }, + }); + + if (discontinue.res?.status !== 200) { + Notification.Error({ + msg: "Failed to discontinue previous prescription", + }); + return; + } + + const { res } = await request(routes.createPrescription, { + pathParams: { consultation_external_id }, + body: { + ...newObj, + // Forcing the medicine to be the same as the old one + medicine: oldObj.medicine_object?.id, + medicine_old: oldObj.medicine_old, + }, + }); + + return res?.status === 201; +}; + +export default function EditPrescriptionForm(props: Props) { + const consultation = useSlug("consultation"); + const [isLoading, setIsLoading] = useState(false); + const { t } = useTranslation(); + + return ( + + disabled={isLoading} + defaults={props.initial} + onCancel={() => props.onDone(false)} + onSubmit={async (obj) => { + setIsLoading(true); + const success = await handleSubmit(consultation, props.initial, obj); + setIsLoading(false); + + if (success) { + props.onDone(true); + } + }} + noPadding + validate={EditPrescriptionFormValidator(props.initial)} + > + {(field) => ( + <> + + +
+ t("PRESCRIPTION_ROUTE_" + key)} + optionValue={(key) => key} + /> + +
+ + {props.initial.is_prn ? ( + <> + + + `${hours} hrs.`} + optionValue={(hours) => hours} + position="above" + /> + + ) : ( +
+ + t("PRESCRIPTION_FREQUENCY_" + key.toUpperCase()) + } + optionValue={([key]) => key} + /> + +
+ )} + + + + )} + + ); +} diff --git a/src/Components/Medicine/PrescriptionAdministrationsTable.tsx b/src/Components/Medicine/PrescriptionAdministrationsTable.tsx index 470caa1042b..c80b66f44c6 100644 --- a/src/Components/Medicine/PrescriptionAdministrationsTable.tsx +++ b/src/Components/Medicine/PrescriptionAdministrationsTable.tsx @@ -20,6 +20,7 @@ import { formatTime, } from "../../Utils/utils"; import useRangePagination from "../../Common/hooks/useRangePagination"; +import EditPrescriptionForm from "./EditPrescriptionForm"; interface DateRange { start: Date; @@ -47,10 +48,8 @@ export default function PrescriptionAdministrationsTable({ const { t } = useTranslation(); const [state, setState] = useState(); - const [showDiscontinued, setShowDiscontinued] = useState(false); const [discontinuedCount, setDiscontinuedCount] = useState(); - const pagination = useRangePagination({ bounds: state?.administrationsTimeBounds ?? { start: new Date(), @@ -58,8 +57,7 @@ export default function PrescriptionAdministrationsTable({ }, perPage: 24 * 60 * 60 * 1000, slots: 24, - snapToLatest: true, - reverse: true, + defaultEnd: true, }); const [showBulkAdminister, setShowBulkAdminister] = useState(false); @@ -159,7 +157,7 @@ export default function PrescriptionAdministrationsTable({ />
- +
)) - : pagination.slots - ?.map(({ start, end }, index) => ( - - )) - .reverse()} + : pagination.slots?.map(({ start, end }, index) => ( + + ))} {showDiscontinue && ( { {t("discontinue")} + { + setShowDetails(false); + setShowEdit(true); + }} + > + + {t("edit")} + { )} - - - - - )) - .reverse()} - + + - - + ))} + + ); }; diff --git a/src/Components/Medicine/PrescriptionDetailCard.tsx b/src/Components/Medicine/PrescriptionDetailCard.tsx index 6da4fa7ae8d..bf27aa34068 100644 --- a/src/Components/Medicine/PrescriptionDetailCard.tsx +++ b/src/Components/Medicine/PrescriptionDetailCard.tsx @@ -5,6 +5,7 @@ import ReadMore from "../Common/components/Readmore"; import ButtonV2 from "../Common/components/ButtonV2"; import { PrescriptionActions } from "../../Redux/actions"; import { useTranslation } from "react-i18next"; +import RecordMeta from "../../CAREUI/display/RecordMeta"; export default function PrescriptionDetailCard({ prescription, @@ -29,7 +30,7 @@ export default function PrescriptionDetailCard({ prescription.discontinued && "bg-gray-200 opacity-80" )} > -
+
@@ -83,7 +84,7 @@ export default function PrescriptionDetailCard({
-
+
{prescription.medicine_object?.name ?? prescription.medicine_old} @@ -146,6 +147,23 @@ export default function PrescriptionDetailCard({ )}
+ +
+ + Prescribed + + + {prescription.discontinued && ( + + and was discontinued + + + )} +
{props.children} diff --git a/src/Components/Medicine/models.ts b/src/Components/Medicine/models.ts index 62aea46b6d2..0c49d199b21 100644 --- a/src/Components/Medicine/models.ts +++ b/src/Components/Medicine/models.ts @@ -1,7 +1,7 @@ import { PerformedByModel } from "../HCX/misc"; interface BasePrescription { - readonly id?: string; + readonly id: string; medicine?: string; medicine_object?: MedibaseMedicine; medicine_old?: string; diff --git a/src/Components/Medicine/validators.ts b/src/Components/Medicine/validators.ts new file mode 100644 index 00000000000..40261646d05 --- /dev/null +++ b/src/Components/Medicine/validators.ts @@ -0,0 +1,49 @@ +import { FieldError, RequiredFieldValidator } from "../Form/FieldValidators"; +import { FormErrors } from "../Form/Utils"; +import { Prescription } from "./models"; + +export const PrescriptionFormValidator = () => { + return (form: Prescription): FormErrors => { + const errors: Partial> = {}; + errors.medicine_object = RequiredFieldValidator()(form.medicine_object); + errors.dosage = RequiredFieldValidator()(form.dosage); + if (form.is_prn) + errors.indicator = RequiredFieldValidator()(form.indicator); + if (!form.is_prn) + errors.frequency = RequiredFieldValidator()(form.frequency); + return errors; + }; +}; + +export const EditPrescriptionFormValidator = (old: Prescription) => { + return (form: Prescription): FormErrors => { + const errors = PrescriptionFormValidator()(form); + + if (comparePrescriptions(old, form)) { + errors.$all = "No changes made"; + } + + return errors; + }; +}; + +const PRESCRIPTION_COMPARE_FIELDS: (keyof Prescription)[] = [ + "medicine", + "days", + "discontinued", + "dosage", + "frequency", + "indicator", + "is_prn", + "max_dosage", + "min_hours_between_doses", + "prescription_type", + "route", +]; + +export const comparePrescriptions = (a: Prescription, b: Prescription) => { + return ( + PRESCRIPTION_COMPARE_FIELDS.every((field) => a[field] === b[field]) && + a.medicine_object?.id === b.medicine_object?.id + ); +}; diff --git a/src/Components/Notifications/NotificationsList.tsx b/src/Components/Notifications/NotificationsList.tsx index f6afa6cccd8..5f124516a14 100644 --- a/src/Components/Notifications/NotificationsList.tsx +++ b/src/Components/Notifications/NotificationsList.tsx @@ -165,6 +165,7 @@ export default function NotificationsList({ const [isMarkingAllAsRead, setIsMarkingAllAsRead] = useState(false); const [isSubscribed, setIsSubscribed] = useState(""); const [isSubscribing, setIsSubscribing] = useState(false); + const [showUnread, setShowUnread] = useState(false); const { t } = useTranslation(); useEffect(() => { @@ -351,33 +352,39 @@ export default function NotificationsList({ } else if (data?.length) { manageResults = ( <> - {data.map((result: any) => ( - - ))} + {data + .filter((notification: any) => + showUnread ? notification.read_at === null : true + ) + .map((result: any) => ( + + ))} {isLoading && (
)} - {totalCount > RESULT_LIMIT && offset < totalCount - RESULT_LIMIT && ( -
- setOffset((prev) => prev + RESULT_LIMIT)} - > - {isLoading ? t("loading") : t("load_more")} - -
- )} + {!showUnread && + totalCount > RESULT_LIMIT && + offset < totalCount - RESULT_LIMIT && ( +
+ setOffset((prev) => prev + RESULT_LIMIT)} + > + {isLoading ? t("loading") : t("load_more")} + +
+ )} ); } else if (data && data.length === 0) { @@ -448,6 +455,21 @@ export default function NotificationsList({ /> {t("mark_all_as_read")} + setShowUnread(!showUnread)} + > + + + + {showUnread + ? t("show_all_notifications") + : t("show_unread_notifications")} + +
{ - console.log("ID:", external_id.id); - const res = await dispatch(getNotificationData({ id: external_id.id })); + const res = await dispatch(getNotificationData({ id })); const data = res.data.caused_objects; switch (res.data.event) { case "PATIENT_CREATED": diff --git a/src/Components/Patient/DailyRounds.tsx b/src/Components/Patient/DailyRounds.tsx index a84ad4a3e8b..ff749aed29e 100644 --- a/src/Components/Patient/DailyRounds.tsx +++ b/src/Components/Patient/DailyRounds.tsx @@ -1,40 +1,40 @@ import { navigate } from "raviger"; -import { useCallback, useState, useEffect, lazy } from "react"; +import dayjs from "dayjs"; +import { lazy, useCallback, useEffect, useState } from "react"; import { useDispatch } from "react-redux"; import { - TELEMEDICINE_ACTIONS, + PATIENT_CATEGORIES, REVIEW_AT_CHOICES, RHYTHM_CHOICES, - PATIENT_CATEGORIES, + TELEMEDICINE_ACTIONS, } from "../../Common/constants"; +import useAppHistory from "../../Common/hooks/useAppHistory"; import { statusType, useAbortableEffect } from "../../Common/utils"; import { createDailyReport, getConsultationDailyRoundsDetails, getDailyReport, - updateDailyReport, getPatient, + updateDailyReport, } from "../../Redux/actions"; +import { DraftSection, useAutoSaveReducer } from "../../Utils/AutoSave"; import * as Notification from "../../Utils/Notifications"; import { formatDateTime } from "../../Utils/utils"; -import TextAreaFormField from "../Form/FormFields/TextAreaFormField"; -import { Cancel, Submit } from "../Common/components/ButtonV2"; -import useAppHistory from "../../Common/hooks/useAppHistory"; -import { DraftSection, useAutoSaveReducer } from "../../Utils/AutoSave"; -import Page from "../Common/components/Page"; -import { FieldChangeEvent } from "../Form/FormFields/Utils"; -import TextFormField from "../Form/FormFields/TextFormField"; -import { SelectFormField } from "../Form/FormFields/SelectFormField"; -import PatientCategorySelect from "./PatientCategorySelect"; -import CheckBoxFormField from "../Form/FormFields/CheckBoxFormField"; -import { SymptomsSelect } from "../Common/SymptomsSelect"; -import RangeAutocompleteFormField from "../Form/FormFields/RangeAutocompleteFormField"; import BloodPressureFormField, { meanArterialPressure, } from "../Common/BloodPressureFormField"; +import { SymptomsSelect } from "../Common/SymptomsSelect"; import TemperatureFormField from "../Common/TemperatureFormField"; -import dayjs from "dayjs"; +import { Cancel, Submit } from "../Common/components/ButtonV2"; +import Page from "../Common/components/Page"; +import CheckBoxFormField from "../Form/FormFields/CheckBoxFormField"; +import RangeAutocompleteFormField from "../Form/FormFields/RangeAutocompleteFormField"; +import { SelectFormField } from "../Form/FormFields/SelectFormField"; +import TextAreaFormField from "../Form/FormFields/TextAreaFormField"; +import TextFormField from "../Form/FormFields/TextFormField"; +import { FieldChangeEvent } from "../Form/FormFields/Utils"; +import PatientCategorySelect from "./PatientCategorySelect"; const Loading = lazy(() => import("../Common/Loading")); const initForm: any = { @@ -44,8 +44,7 @@ const initForm: any = { other_details: "", patient_category: "", current_health: 0, - recommend_discharge: false, - action: null, + actions: null, review_interval: 0, admitted_to: "", taken_at: null, @@ -274,7 +273,6 @@ export const DailyRounds = (props: any) => { physical_examination_info: state.form.physical_examination_info, other_details: state.form.other_details, consultation: consultationId, - recommend_discharge: JSON.parse(state.form.recommend_discharge), action: prevAction, review_interval: Number(prevReviewInterval), }; @@ -516,12 +514,6 @@ export const DailyRounds = (props: any) => { }} /> - - {state.form.rounds_type === "NORMAL" && ( <>

Vitals

diff --git a/src/Components/Patient/FileUpload.tsx b/src/Components/Patient/FileUpload.tsx index fe0881e6994..f4d02404b7f 100644 --- a/src/Components/Patient/FileUpload.tsx +++ b/src/Components/Patient/FileUpload.tsx @@ -100,7 +100,7 @@ interface FileUploadProps { hideBack: boolean; audio?: boolean; unspecified: boolean; - sampleId?: number; + sampleId?: string; claimId?: string; } @@ -1523,6 +1523,7 @@ export const FileUpload = (props: FileUploadProps) => { {t("choose_file")} { Open Camera handleUpload({ status })} diff --git a/src/Components/Patient/ManagePatients.tsx b/src/Components/Patient/ManagePatients.tsx index 6e83eb9bc91..61b18faa367 100644 --- a/src/Components/Patient/ManagePatients.tsx +++ b/src/Components/Patient/ManagePatients.tsx @@ -185,6 +185,8 @@ export const PatientManager = () => { qParams.date_declared_positive_after || undefined, date_of_result_before: qParams.date_of_result_before || undefined, date_of_result_after: qParams.date_of_result_after || undefined, + last_consultation_medico_legal_case: + qParams.last_consultation_medico_legal_case || undefined, last_consultation_admission_date_before: qParams.last_consultation_admission_date_before || undefined, last_consultation_admission_date_after: @@ -333,6 +335,7 @@ export const PatientManager = () => { }); }, [ dispatch, + qParams.last_consultation_medico_legal_case, qParams.last_consultation_admission_date_before, qParams.last_consultation_admission_date_after, qParams.last_consultation_discharge_date_before, @@ -768,11 +771,11 @@ export const PatientManager = () => {
updateQuery({ is_active: "True" })} onClickTab2={() => updateQuery({ is_active: "False" })} - activeTab={tabValue ? true : false} + isTab2Active={tabValue ? true : false} /> {showDoctorConnect && ( { }} className="mr-5 w-full lg:w-fit" > - + Export ) : ( @@ -932,6 +935,10 @@ export const PatientManager = () => { kasp(), badge("COWIN ID", "covin_id"), badge("Is Antenatal", "is_antenatal"), + badge( + "Is Medico-Legal Case", + "last_consultation_medico_legal_case" + ), value("Facility", "facility", facilityBadgeName), badge("Facility Type", "facility_type"), value("District", "district", districtName), diff --git a/src/Components/Patient/PatientFilter.tsx b/src/Components/Patient/PatientFilter.tsx index 205ac39ac9c..97f5a6c6b9c 100644 --- a/src/Components/Patient/PatientFilter.tsx +++ b/src/Components/Patient/PatientFilter.tsx @@ -65,6 +65,8 @@ export default function PatientFilter(props: any) { age_max: filter.age_max || null, date_of_result: filter.date_of_result || null, date_declared_positive: filter.date_declared_positive || null, + last_consultation_medico_legal_case: + filter.last_consultation_medico_legal_case || null, last_consultation_admission_date_before: filter.last_consultation_admission_date_before || null, last_consultation_admission_date_after: @@ -120,6 +122,7 @@ export default function PatientFilter(props: any) { age_max: "", date_of_result: null, date_declared_positive: null, + last_consultation_medico_legal_case: null, last_consultation_admission_date_before: "", last_consultation_admission_date_after: "", last_consultation_discharge_date_before: "", @@ -229,6 +232,7 @@ export default function PatientFilter(props: any) { age_min, age_max, date_of_result, + last_consultation_medico_legal_case, last_consultation_admission_date_before, last_consultation_admission_date_after, last_consultation_discharge_date_before, @@ -266,6 +270,8 @@ export default function PatientFilter(props: any) { modified_date_before: dateQueryString(modified_date_before), modified_date_after: dateQueryString(modified_date_after), date_of_result: dateQueryString(date_of_result), + last_consultation_medico_legal_case: + last_consultation_medico_legal_case || "", last_consultation_admission_date_before: dateQueryString( last_consultation_admission_date_before ), @@ -473,6 +479,23 @@ export default function PatientFilter(props: any) { } />
+
+ Is Medico-Legal Case + + o === "true" ? "Medico-Legal" : "Non-Medico-Legal" + } + value={filterState.last_consultation_medico_legal_case} + onChange={(v) => + setFilterState({ + ...filterState, + last_consultation_medico_legal_case: v, + }) + } + /> +
{ + if (!consultation?.id || value === medicoLegalCase) return; + const { res, data } = await request(routes.partialUpdateConsultation, { + pathParams: { id: consultation?.id }, + body: { medico_legal_case: value }, + }); + + if (res?.status !== 200 || !data) { + Notification.Error({ + msg: "Failed to update Medico Legal Case", + }); + setMedicoLegalCase(!value); + } else { + Notification.Success({ + msg: "Medico Legal Case updated successfully", + }); + } + }; + return ( <> 0 && (
)} + {medicoLegalCase && ( + + MLC + + )}
{!!consultation?.discharge_date && (

Discharged from CARE

)} -

- {formatAge(patient.age, patient.date_of_birth, true)} - • - {patient.gender} - {consultation?.suggestion === "DC" && ( - <> - • - - - Domiciliary Care - - - )} - {consultation?.is_readmission && ( - <> - • - - - Readmitted - - - )} -

+
+
+ {patient.action && patient.action != 10 && ( +
+
+ + {" "} + { + TELEMEDICINE_ACTIONS.find( + (i) => i.id === patient.action + )?.desc + } + +
+
+ )} +
+
+ Age: {patient.age} years +
+
+
+
+ Gender: {patient.gender} +
+
+ {consultation?.suggestion === "DC" && ( +
+
+
+ Domiciliary Care + +
+
+
+ )} +
+
{[ ["Blood Group", patient.blood_group, patient.blood_group], @@ -310,131 +359,225 @@ export default function PatientInfoCard(props: {
, ], ], - [ - `/patient/${patient.id}/investigation_reports`, - "Investigation Summary", - "align-alt", - true, - ], - [ - `/facility/${patient.facility}/patient/${patient.id}/consultation/${consultation?.id}/treatment-summary`, - "Treatment Summary", - "file-medical", - consultation?.id, - ], - ] - .concat( - enable_hcx - ? [ - [ - `/facility/${patient.facility}/patient/${patient.id}/consultation/${consultation?.id}/claims`, - "Claims", - "copy-landscape", - consultation?.id, - ], - ] - : [] - ) - .map( - (action: any, i) => - action[3] && ( -
- + action[3] && ( +
+ { + if ( consultation?.admitted && !consultation?.current_bed && i === 1 - ? undefined - : `${action[0]}` + ) { + Notification.Error({ + msg: "Please assign a bed to the patient", + }); + setOpen(true); } - onClick={() => { - if ( - consultation?.admitted && - !consultation?.current_bed && - i === 1 - ) { - Notification.Error({ - msg: "Please assign a bed to the patient", - }); - setOpen(true); - } - }} - className="w-full" - > - - -

{action[1]}

-
-
- {action[4] && action[4][0] && ( - <> -

- {action[4][1]} -

- - )} -
+ }} + className="w-full" + > + + +

{action[1]}

+
+
+ {action?.[4]?.[0] && ( + <> +

+ {action[4][1]} +

+ + )} +
+ ) + )} + } + > +
+ {[ + [ + `/patient/${patient.id}/investigation_reports`, + "Investigation Summary", + "align-alt", + true, + ], + [ + `/facility/${patient.facility}/patient/${patient.id}/consultation/${consultation?.id}/treatment-summary`, + "Treatment Summary", + "file-medical", + consultation?.id, + ], + ] + .concat( + enable_hcx + ? [ + [ + `/facility/${patient.facility}/patient/${patient.id}/consultation/${consultation?.id}/claims`, + "Claims", + "copy-landscape", + consultation?.id, + ], + ] + : [] ) - )} - {enable_abdm && - (patient.abha_number ? ( - <> - setShowABHAProfile(true)} - > - - -

Show ABHA Profile

-
-
- setShowLinkCareContext(true)} - > - - -

Link Care Context

-
-
- setShowABHAProfile(false)} - /> - setShowLinkCareContext(false)} - /> - - ) : ( - <> - setShowLinkABHANumber(true)} - > - - -

Link ABHA Number

-
-
- setShowLinkABHANumber(false)} - patientId={patient.id as any} - onSuccess={(_) => { - window.location.href += "?show-abha-profile=true"; + .map( + (action: any, i) => + action[3] && ( + + ) + )} +
+
+ {enable_abdm && + (patient.abha_number ? ( + <> + + {({ close }) => ( + <> +
{ + close(); + setShowABHAProfile(true); + }} + > + + Show ABHA Profile +
+
{ + close(); + setShowLinkCareContext(true); + }} + > + + Link Care Context +
+ + )} +
+ + ) : ( + + {({ close }) => ( +
{ + close(); + setShowLinkABHANumber(true); + }} + > + + +

Link ABHA Number

+
+
+ )} +
+ ))} +
+
+ + { + setMedicoLegalCase(checked); + switchMedicoLegalCase(checked); }} - /> - - ))} + className={classNames( + medicoLegalCase ? "bg-primary" : "bg-gray-200", + "relative inline-flex h-4 w-8 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none " + )} + > + + + + Medico-Legal Case + {" "} + + +
+
+ setShowLinkABHANumber(false)} + patientId={patient.id as any} + onSuccess={(_) => { + window.location.href += "?show-abha-profile=true"; + }} + /> + setShowABHAProfile(false)} + /> + setShowLinkCareContext(false)} + /> ); } diff --git a/src/Components/Patient/PatientNotes.tsx b/src/Components/Patient/PatientNotes.tsx index 68a5ab4dc5d..c105619678b 100644 --- a/src/Components/Patient/PatientNotes.tsx +++ b/src/Components/Patient/PatientNotes.tsx @@ -114,6 +114,7 @@ const PatientNotes = (props: PatientNotesProps) => { />

Add new notes

@@ -184,9 +182,9 @@ export default function PrescriptionAdministrationsTable({ border className="mx-2 px-1" variant="secondary" - disabled={!pagination.hasNext} - onClick={pagination.next} - tooltip="Next 24 hours" + disabled={!pagination.hasPrevious} + onClick={pagination.previous} + tooltip="Previous 24 hours" tooltipClassName="tooltip-bottom -translate-x-1/2 text-xs" > @@ -201,26 +199,24 @@ export default function PrescriptionAdministrationsTable({

-

{formatDateTime(end, "DD/MM")}

-

{formatDateTime(end, "HH:mm")}

- - - Administration(s) between -
- {formatTime(start)} and{" "} - {formatTime(end)} -
- on {formatDate(start)} -
-
+

{formatDateTime(start, "DD/MM")}

+

{formatDateTime(start, "HH:mm")}

+ + + Administration(s) between +
+ {formatTime(start)} and{" "} + {formatTime(end)} +
+ on {formatDate(start)} +
+
@@ -299,6 +295,7 @@ const PrescriptionRow = ({ prescription, ...props }: PrescriptionRowProps) => { const { t } = useTranslation(); // const [showActions, setShowActions] = useState(false); const [showDetails, setShowDetails] = useState(false); + const [showEdit, setShowEdit] = useState(false); const [showAdminister, setShowAdminister] = useState(false); const [showDiscontinue, setShowDiscontinue] = useState(false); const [administrations, setAdministrations] = @@ -328,7 +325,11 @@ const PrescriptionRow = ({ prescription, ...props }: PrescriptionRowProps) => { }, [prescription.id, dispatch, props.intervals]); return ( - <> +
setShowDetails(true)} + {showEdit && ( + setShowEdit(false)} + show={showEdit} + title={`${t("edit")} ${t( + prescription.is_prn ? "prn_prescription" : "prescription_medication" + )}: ${ + prescription.medicine_object?.name ?? prescription.medicine_old + }`} + description={ +
+ + {t("edit_caution_note")} +
+ } + className="w-full max-w-3xl lg:min-w-[600px]" > -
-
- - {prescription.medicine_object?.name ?? - prescription.medicine_old} - - - {prescription.discontinued && ( - - {t("discontinued")} - + { + setShowEdit(false); + if (success) { + props.refetch(); + } + }} + /> + + )} +
setShowDetails(true)} + > +
+
+ + {prescription.medicine_object?.name ?? prescription.medicine_old} + - {prescription.route && ( - - {t(prescription.route)} - - )} -
+ {prescription.discontinued && ( + + {t("discontinued")} + + )} -
-

{prescription.dosage}

-

- {!prescription.is_prn - ? t("PRESCRIPTION_FREQUENCY_" + prescription.frequency) - : prescription.indicator} -

-
+ {prescription.route && ( + + {t(prescription.route)} + + )}
-
- {/* Administration Cells */} - {props.intervals - .map(({ start, end }, index) => ( - - {administrations === undefined ? ( - - ) : ( - - )} - - {/* Action Buttons */} - - setShowAdminister(true)} - > - {t("administer")} - +
+

{prescription.dosage}

+

+ {!prescription.is_prn + ? t("PRESCRIPTION_FREQUENCY_" + prescription.frequency) + : prescription.indicator} +

+
+ +
+ {/* Administration Cells */} + {props.intervals.map(({ start, end }, index) => ( + + {administrations === undefined ? ( + + ) : ( + + )}
+ + {/* Action Buttons */} + + setShowAdminister(true)} + > + {t("administer")} + +