diff --git a/api/.pipeline/config.js b/api/.pipeline/config.js index 7d6556d3f1..ac506c9645 100644 --- a/api/.pipeline/config.js +++ b/api/.pipeline/config.js @@ -218,7 +218,7 @@ const phases = { s3KeyPrefix: 'sims', tz: config.timezone.api, sso: config.sso.prod, - featureFlags: 'API_FF_SUBMIT_BIOHUB', + featureFlags: 'API_FF_SUBMIT_BIOHUB,API_FF_DISABLE_MULTIPLE_ACTIVE_DEPLOYMENTS_CHECK', logLevel: 'silent', logLevelFile: 'debug', logFileDir: 'data/logs', diff --git a/api/src/paths/project/{projectId}/survey/{surveyId}/deployments/delete.ts b/api/src/paths/project/{projectId}/survey/{surveyId}/deployments/delete.ts index b03200296c..95f363c957 100644 --- a/api/src/paths/project/{projectId}/survey/{surveyId}/deployments/delete.ts +++ b/api/src/paths/project/{projectId}/survey/{surveyId}/deployments/delete.ts @@ -133,6 +133,8 @@ export function deleteDeploymentsInSurvey(): RequestHandler { await Promise.all(deletePromises); + await connection.commit(); + return res.status(200).send(); } catch (error) { defaultLog.error({ label: 'deleteDeploymentsInSurvey', message: 'error', error }); diff --git a/api/src/paths/project/{projectId}/survey/{surveyId}/deployments/index.ts b/api/src/paths/project/{projectId}/survey/{surveyId}/deployments/index.ts index afccc5b679..89739a04ae 100644 --- a/api/src/paths/project/{projectId}/survey/{surveyId}/deployments/index.ts +++ b/api/src/paths/project/{projectId}/survey/{surveyId}/deployments/index.ts @@ -9,6 +9,7 @@ import { authorizeRequestHandler } from '../../../../../../request-handlers/secu import { BctwDeploymentService } from '../../../../../../services/bctw-service/bctw-deployment-service'; import { ICritterbaseUser } from '../../../../../../services/critterbase-service'; import { DeploymentService } from '../../../../../../services/deployment-service'; +import { isFeatureFlagPresent } from '../../../../../../utils/feature-flag-utils'; import { getLogger } from '../../../../../../utils/logger'; const defaultLog = getLogger('paths/project/{projectId}/survey/{surveyId}/deployments/index'); @@ -152,25 +153,27 @@ export function getDeploymentsInSurvey(): RequestHandler { (deployment) => deployment.deployment_id === surveyDeployment.bctw_deployment_id ); - if (matchingBctwDeployments.length > 1) { - defaultLog.warn({ - label: 'getDeploymentById', - message: 'Multiple active deployments found for the same deployment ID, when only one should exist.', - sims_deployment_id: surveyDeployment.deployment_id, - bctw_deployment_id: surveyDeployment.bctw_deployment_id - }); - - badDeployments.push({ - name: 'BCTW Data Error', - message: 'Multiple active deployments found for the same deployment ID, when only one should exist.', - data: { + // TODO: If the feature flag exists, then we allow multiple active deployments to exist for the same deployment + // ID (when normally we would return a bad deployment). + if (!isFeatureFlagPresent(['API_FF_DISABLE_MULTIPLE_ACTIVE_DEPLOYMENTS_CHECK'])) { + if (matchingBctwDeployments.length > 1) { + defaultLog.warn({ + label: 'getDeploymentById', + message: 'Multiple active deployments found for the same deployment ID, when only one should exist.', sims_deployment_id: surveyDeployment.deployment_id, bctw_deployment_id: surveyDeployment.bctw_deployment_id - } - }); - - // Don't continue processing this deployment - continue; + }); + badDeployments.push({ + name: 'BCTW Data Error', + message: 'Multiple active deployments found for the same deployment ID, when only one should exist.', + data: { + sims_deployment_id: surveyDeployment.deployment_id, + bctw_deployment_id: surveyDeployment.bctw_deployment_id + } + }); + // Don't continue processing this deployment + continue; + } } if (matchingBctwDeployments.length === 0) { diff --git a/api/src/repositories/observation-subcount-environment-repository.ts b/api/src/repositories/observation-subcount-environment-repository.ts index 6e6bc99459..c68c2d28a1 100644 --- a/api/src/repositories/observation-subcount-environment-repository.ts +++ b/api/src/repositories/observation-subcount-environment-repository.ts @@ -285,7 +285,7 @@ export class ObservationSubCountEnvironmentRepository extends BaseRepository { surveyId: number ): Promise { const sqlStatement = SQL` - SELECT + SELECT DISTINCT environment_quantitative.environment_quantitative_id, environment_quantitative.name, environment_quantitative.description, diff --git a/app/.pipeline/config.js b/app/.pipeline/config.js index df25c0403c..9feb686da4 100644 --- a/app/.pipeline/config.js +++ b/app/.pipeline/config.js @@ -164,7 +164,7 @@ const phases = { maxUploadFileSize, nodeEnv: 'production', sso: config.sso.prod, - featureFlags: 'APP_FF_SUBMIT_BIOHUB', + featureFlags: 'APP_FF_SUBMIT_BIOHUB,APP_FF_DISABLE_BAD_DEPLOYMENT_DELETE', cpuRequest: '50m', cpuLimit: '1000m', memoryRequest: '100Mi', diff --git a/app/src/components/layout/Header.tsx b/app/src/components/layout/Header.tsx index 0e52a07142..1c87ee0caa 100644 --- a/app/src/components/layout/Header.tsx +++ b/app/src/components/layout/Header.tsx @@ -385,8 +385,8 @@ const Header: React.FC = () => { For technical support or questions about this application, please email ‌ - - biohub@gov.bc.ca + + spi_mail@gov.bc.ca diff --git a/app/src/components/species/components/SpeciesCard.tsx b/app/src/components/species/components/SpeciesCard.tsx index a4f11013aa..685eb665ce 100644 --- a/app/src/components/species/components/SpeciesCard.tsx +++ b/app/src/components/species/components/SpeciesCard.tsx @@ -34,14 +34,7 @@ const SpeciesCard = (props: ISpeciesCardProps) => { {commonNames} - + ); }; diff --git a/app/src/features/surveys/animals/animal-form/components/general-information/components/SelectedAnimalSpecies.tsx b/app/src/features/surveys/animals/animal-form/components/general-information/components/SelectedAnimalSpecies.tsx index 122d0f7b15..74ae85ee57 100644 --- a/app/src/features/surveys/animals/animal-form/components/general-information/components/SelectedAnimalSpecies.tsx +++ b/app/src/features/surveys/animals/animal-form/components/general-information/components/SelectedAnimalSpecies.tsx @@ -25,7 +25,7 @@ const SelectedAnimalSpecies = (props: ISelectedAnimalSpeciesProps) => { {selectedSpecies.map((species, speciesIndex) => { return ( - + diff --git a/app/src/features/surveys/animals/list/AnimalListContainer.tsx b/app/src/features/surveys/animals/list/AnimalListContainer.tsx index 88b908f014..79d3f41b5f 100644 --- a/app/src/features/surveys/animals/list/AnimalListContainer.tsx +++ b/app/src/features/surveys/animals/list/AnimalListContainer.tsx @@ -327,7 +327,7 @@ export const AnimalListContainer = () => { control={ 0 && checkboxSelectedIds.length === crittersCount} indeterminate={checkboxSelectedIds.length >= 1 && checkboxSelectedIds.length < crittersCount} @@ -352,6 +352,7 @@ export const AnimalListContainer = () => { {critters?.map((critter) => ( { }> - + { {selectedSpecies.map((species, index) => ( - + { - - - - Sampling Sites ‌ - - ({sampleSiteCount}) - + + + Sampling Sites ‌ + + ({sampleSiteCount}) - - - - - + + + + + + - + - - - - - - } - isLoadingFallbackDelay={100}> - + + + + + + } + isLoadingFallbackDelay={100}> + - {/* Toggle buttons for changing between sites, methods, and periods */} - + {/* Toggle buttons for changing between sites, methods, and periods */} + - + - {/* Data tables */} - - {activeView === SamplingSiteManageTableView.SITES && ( - } - isLoadingFallbackDelay={100} - hasNoData={!viewCounts[SamplingSiteManageTableView.SITES]} - hasNoDataFallback={ - - } - hasNoDataFallbackDelay={100}> - + {activeView === SamplingSiteManageTableView.SITES && ( + } + isLoadingFallbackDelay={100} + hasNoData={!viewCounts[SamplingSiteManageTableView.SITES]} + hasNoDataFallback={ + - - )} + } + hasNoDataFallbackDelay={100}> + + + )} - {activeView === SamplingSiteManageTableView.PERIODS && ( - } - isLoadingFallbackDelay={100} - hasNoData={!viewCounts[SamplingSiteManageTableView.PERIODS]} - hasNoDataFallback={ - - } - hasNoDataFallbackDelay={100}> - - - )} - - - - + {activeView === SamplingSiteManageTableView.PERIODS && ( + } + isLoadingFallbackDelay={100} + hasNoData={!viewCounts[SamplingSiteManageTableView.PERIODS]} + hasNoDataFallback={ + + } + hasNoDataFallbackDelay={100}> + + + )} + + + ); }; diff --git a/app/src/features/surveys/sampling-information/techniques/create/CreateTechniquePage.tsx b/app/src/features/surveys/sampling-information/techniques/create/CreateTechniquePage.tsx index c44f9db7d0..d57af2f4e6 100644 --- a/app/src/features/surveys/sampling-information/techniques/create/CreateTechniquePage.tsx +++ b/app/src/features/surveys/sampling-information/techniques/create/CreateTechniquePage.tsx @@ -61,6 +61,7 @@ export const CreateTechniquePage = () => { // Parse the form data into the request format const createTechniqueRequestData: ICreateTechniqueRequest = { ...values, + distance_threshold: values.distance_threshold || null, attributes: { qualitative_attributes: values.attributes .filter(({ attribute_type }) => attribute_type === 'qualitative') diff --git a/app/src/features/surveys/sampling-information/techniques/edit/EditTechniquePage.tsx b/app/src/features/surveys/sampling-information/techniques/edit/EditTechniquePage.tsx index 4ed1ce7ba9..0bb5106fbb 100644 --- a/app/src/features/surveys/sampling-information/techniques/edit/EditTechniquePage.tsx +++ b/app/src/features/surveys/sampling-information/techniques/edit/EditTechniquePage.tsx @@ -96,6 +96,7 @@ export const EditTechniquePage = () => { const formattedTechniqueObject: IUpdateTechniqueRequest = { ...values, + distance_threshold: values.distance_threshold || null, attributes: { quantitative_attributes: values.attributes .filter((attribute) => attribute.attribute_type === 'quantitative') diff --git a/app/src/features/surveys/sampling-information/techniques/table/SamplingTechniqueTable.tsx b/app/src/features/surveys/sampling-information/techniques/table/SamplingTechniqueTable.tsx index 2d1aeaab9a..449e1c6bfa 100644 --- a/app/src/features/surveys/sampling-information/techniques/table/SamplingTechniqueTable.tsx +++ b/app/src/features/surveys/sampling-information/techniques/table/SamplingTechniqueTable.tsx @@ -130,12 +130,10 @@ export const SamplingTechniqueTable = (props: ISamp flex: 0.4, headerName: 'Method', renderCell: (params) => ( - - - + ) }, { diff --git a/app/src/features/surveys/telemetry/deployments/create/CreateDeploymentPage.tsx b/app/src/features/surveys/telemetry/deployments/create/CreateDeploymentPage.tsx index 319d87c619..55c2332bc2 100644 --- a/app/src/features/surveys/telemetry/deployments/create/CreateDeploymentPage.tsx +++ b/app/src/features/surveys/telemetry/deployments/create/CreateDeploymentPage.tsx @@ -56,7 +56,7 @@ export const CreateDeploymentPage = () => { await biohubApi.survey.createDeployment(surveyContext.projectId, surveyContext.surveyId, critter_id, { device_id: Number(values.device_id), device_make: values.device_make, - frequency: values.frequency, + frequency: values.frequency || null, frequency_unit: values.frequency_unit, device_model: values.device_model, critterbase_start_capture_id: values.critterbase_start_capture_id, diff --git a/app/src/features/surveys/telemetry/list/SurveyBadDeploymentListItem.tsx b/app/src/features/surveys/telemetry/list/SurveyBadDeploymentListItem.tsx index 6fd7adc17d..47b0f21dda 100644 --- a/app/src/features/surveys/telemetry/list/SurveyBadDeploymentListItem.tsx +++ b/app/src/features/surveys/telemetry/list/SurveyBadDeploymentListItem.tsx @@ -10,6 +10,7 @@ import IconButton from '@mui/material/IconButton'; import List from '@mui/material/List'; import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; +import { FeatureFlagGuard } from 'components/security/Guards'; import { WarningSchema } from 'interfaces/useBioHubApi.interface'; export interface ISurveyBadDeploymentListItemProps { @@ -68,16 +69,28 @@ export const SurveyBadDeploymentListItem = (props: ISurveyBadDeploymentListItemP pr: 2, overflow: 'hidden' }}> - { - event.stopPropagation(); - handleCheckboxChange(data.data.sims_deployment_id); - }} - inputProps={{ 'aria-label': 'controlled' }} - /> + {/* TODO: This delete is commented out as a temporary bug fix to prevent deployment data from being deleted */} + + }> + { + event.stopPropagation(); + handleCheckboxChange(data.data.sims_deployment_id); + }} + inputProps={{ 'aria-label': 'controlled' }} + /> + - handleDelete(data.data.sims_deployment_id as number)} - aria-label="deployment-settings"> - - + {/* TODO: This delete is commented out as a temporary bug fix to prevent deployment data from being deleted */} + + handleDelete(data.data.sims_deployment_id as number)} + aria-label="deployment-settings"> + + + { // Select all const deploymentIds = deployments.map((deployment) => deployment.deployment_id); - const badDeploymentIds = badDeployments.map( - (deployment) => deployment.data.sims_deployment_id - ); - setCheckboxSelectedIds([...badDeploymentIds, ...deploymentIds]); + // const badDeploymentIds = badDeployments.map( + // (deployment) => deployment.data.sims_deployment_id + // ); + // TODO: Temporary bug fix - prevent bad deployment ids from being selected and deleted + setCheckboxSelectedIds([...deploymentIds]); }} inputProps={{ 'aria-label': 'controlled' }} /> @@ -408,6 +410,12 @@ export const SurveyDeploymentList = (props: ISurveyDeploymentListProps) => { sx={{ background: grey[100] }}> + {badDeployments.map((badDeployment) => { return (