diff --git a/api/src/paths/codes.ts b/api/src/paths/codes.ts index ca5f7966ca..b4792d798d 100644 --- a/api/src/paths/codes.ts +++ b/api/src/paths/codes.ts @@ -122,6 +122,9 @@ GET.apiDoc = { }, name: { type: 'string' + }, + description: { + type: 'string' } } } diff --git a/api/src/repositories/code-repository.ts b/api/src/repositories/code-repository.ts index 7dff82bbcc..2e54932eb9 100644 --- a/api/src/repositories/code-repository.ts +++ b/api/src/repositories/code-repository.ts @@ -29,6 +29,8 @@ const DeviceMakeCode = ICode.extend({ description: z.string() }); const FrequencyUnitCode = ICode.extend({ description: z.string() }); const AlertTypeCode = ICode.extend({ description: z.string() }); const VantageCode = ICode.extend({ description: z.string() }); +const TypeCode = ICode.extend({ description: z.string() }); +const SiteSelectionStrategyCode = ICode.extend({ description: z.string() }); export const IAllCodeSets = z.object({ management_action_type: CodeSet(), @@ -173,13 +175,14 @@ export class CodeRepository extends BaseRepository { const sqlStatement = SQL` SELECT type_id as id, - name + name, + description FROM type WHERE record_end_date is null; `; - const response = await this.connection.sql(sqlStatement, ICode); + const response = await this.connection.sql(sqlStatement, TypeCode); return response.rows; } @@ -319,7 +322,8 @@ export class CodeRepository extends BaseRepository { const sqlStatement = SQL` SELECT project_role_id as id, - name + name, + description FROM project_role WHERE record_end_date is null ORDER BY @@ -341,7 +345,8 @@ export class CodeRepository extends BaseRepository { const sqlStatement = SQL` SELECT survey_job_id as id, - name + name, + description FROM survey_job WHERE record_end_date is null; `; @@ -361,12 +366,13 @@ export class CodeRepository extends BaseRepository { const sqlStatement = SQL` SELECT ss.site_strategy_id as id, - ss.name + ss.name, + ss.description FROM site_strategy ss WHERE record_end_date is null; `; - const response = await this.connection.sql(sqlStatement, ICode); + const response = await this.connection.sql(sqlStatement, SiteSelectionStrategyCode); return response.rows; } diff --git a/app/src/components/fields/MultiAutocompleteField.tsx b/app/src/components/fields/MultiAutocompleteField.tsx index 56323d10e0..4300b22e03 100644 --- a/app/src/components/fields/MultiAutocompleteField.tsx +++ b/app/src/components/fields/MultiAutocompleteField.tsx @@ -18,7 +18,7 @@ import { useEffect, useState } from 'react'; export interface IMultiAutocompleteFieldOption { value: string | number; label: string; - subText?: string; + description?: string; } export interface IMultiAutocompleteField { @@ -133,7 +133,7 @@ const MultiAutocompleteField: React.FC = (props) => { filterOptions={createFilterOptions({ limit: props.filterLimit })} renderOption={(renderProps, renderOption, { selected }) => { return ( - + } checkedIcon={} @@ -142,7 +142,7 @@ const MultiAutocompleteField: React.FC = (props) => { value={renderOption.value} color="default" /> - + ); }} diff --git a/app/src/components/fields/MultiAutocompleteFieldVariableSize.tsx b/app/src/components/fields/MultiAutocompleteFieldVariableSize.tsx index 450d93fe6e..dbd7004669 100644 --- a/app/src/components/fields/MultiAutocompleteFieldVariableSize.tsx +++ b/app/src/components/fields/MultiAutocompleteFieldVariableSize.tsx @@ -3,6 +3,7 @@ import CheckBoxOutlineBlank from '@mui/icons-material/CheckBoxOutlineBlank'; import Autocomplete, { AutocompleteInputChangeReason, createFilterOptions } from '@mui/material/Autocomplete'; import Box from '@mui/material/Box'; import Checkbox from '@mui/material/Checkbox'; +import ListItemText from '@mui/material/ListItemText'; import ListSubheader from '@mui/material/ListSubheader'; import TextField from '@mui/material/TextField'; import { FilterOptionsState } from '@mui/material/useAutocomplete'; @@ -12,14 +13,10 @@ import { DebouncedFunc } from 'lodash-es'; import get from 'lodash-es/get'; import React, { useEffect, useState } from 'react'; import { ListChildComponentProps, VariableSizeList } from 'react-window'; +import { IMultiAutocompleteFieldOption } from './MultiAutocompleteField'; const LISTBOX_PADDING = 8; // px -export interface IMultiAutocompleteFieldOption { - value: string | number; - label: string; -} - // Params required to make MultiAutocompleteField use API to populate search results export type ApiSearchTypeParam = { type: 'api-search'; @@ -270,7 +267,7 @@ const MultiAutocompleteFieldVariableSize: React.FC = (p filterOptions={handleFiltering} renderOption={(renderProps, renderOption, { selected }) => { return ( - + } checkedIcon={} @@ -280,7 +277,7 @@ const MultiAutocompleteFieldVariableSize: React.FC = (p value={renderOption.value} color="default" /> - {renderOption.label} + ); }} diff --git a/app/src/components/user/UserRoleSelector.test.tsx b/app/src/components/user/UserRoleSelector.test.tsx index f2b7a21d10..7ceb3b71b3 100644 --- a/app/src/components/user/UserRoleSelector.test.tsx +++ b/app/src/components/user/UserRoleSelector.test.tsx @@ -1,19 +1,18 @@ import { PROJECT_ROLE } from 'constants/roles'; -import { ICode } from 'interfaces/useCodesApi.interface'; +import { IGetAllCodeSetsResponse } from 'interfaces/useCodesApi.interface'; import { fireEvent, render, waitFor } from 'test-helpers/test-utils'; import UserRoleSelector from './UserRoleSelector'; -const roles: ICode[] = [ + +const mockRoles: IGetAllCodeSetsResponse['project_roles'] = [ { id: 1, - name: PROJECT_ROLE.COLLABORATOR + name: PROJECT_ROLE.COORDINATOR, + description: 'The administrative lead of the project.' }, { id: 2, - name: PROJECT_ROLE.COORDINATOR - }, - { - id: 3, - name: PROJECT_ROLE.OBSERVER + name: PROJECT_ROLE.COLLABORATOR, + description: 'A participant team member of the project.' } ]; @@ -35,7 +34,7 @@ describe('UserRoleSelector', () => { agency: 'Business', project_role_names: [PROJECT_ROLE.COORDINATOR] }} - roles={roles} + roles={mockRoles} error={undefined} selectedRole={PROJECT_ROLE.COORDINATOR} handleAdd={() => {}} @@ -68,7 +67,7 @@ describe('UserRoleSelector', () => { agency: 'Business', project_role_names: [PROJECT_ROLE.COORDINATOR] }} - roles={roles} + roles={mockRoles} error={undefined} selectedRole={PROJECT_ROLE.COORDINATOR} handleAdd={() => {}} @@ -106,7 +105,7 @@ describe('UserRoleSelector', () => { agency: 'Business', project_role_names: [] }} - roles={roles} + roles={mockRoles} error={undefined} selectedRole={''} handleAdd={onAdd} diff --git a/app/src/components/user/UserRoleSelector.tsx b/app/src/components/user/UserRoleSelector.tsx index fbfcf2adf1..018e9c6c3b 100644 --- a/app/src/components/user/UserRoleSelector.tsx +++ b/app/src/components/user/UserRoleSelector.tsx @@ -8,7 +8,7 @@ import Paper from '@mui/material/Paper'; import Select from '@mui/material/Select'; import Typography from '@mui/material/Typography'; import { PROJECT_ROLE_ICONS } from 'constants/roles'; -import { ICode } from 'interfaces/useCodesApi.interface'; +import { IGetAllCodeSetsResponse } from 'interfaces/useCodesApi.interface'; import { IGetProjectParticipant } from 'interfaces/useProjectApi.interface'; import { IGetSurveyParticipant } from 'interfaces/useSurveyApi.interface'; import { ISystemUser } from 'interfaces/useUserApi.interface'; @@ -18,11 +18,12 @@ interface IUserRoleSelectorProps { index: number; user: ISystemUser | IGetProjectParticipant | IGetSurveyParticipant; selectedRole: string; - roles: ICode[]; + roles: IGetAllCodeSetsResponse['project_roles']; error: JSX.Element | undefined; handleAdd: (role: string, index: number) => void; handleRemove: (id: number) => void; label: string; + description?: string; } const UserRoleSelector: React.FC = (props) => { @@ -79,14 +80,26 @@ const UserRoleSelector: React.FC = (props) => { ); }}> {roles.map((item) => ( - - {item.name} - {PROJECT_ROLE_ICONS[item.name] && ( - <> -   - - - )} + + + {item.name} + {PROJECT_ROLE_ICONS[item.name] && ( + <> +   + + + )} + + + {item.description} + ))} diff --git a/app/src/features/projects/components/ProjectIUCNForm.test.tsx b/app/src/features/projects/components/ProjectIUCNForm.test.tsx index 4a2054126e..05313dbb94 100644 --- a/app/src/features/projects/components/ProjectIUCNForm.test.tsx +++ b/app/src/features/projects/components/ProjectIUCNForm.test.tsx @@ -1,4 +1,4 @@ -import { IMultiAutocompleteFieldOption } from 'components/fields/MultiAutocompleteFieldVariableSize'; +import { IMultiAutocompleteFieldOption } from 'components/fields/MultiAutocompleteField'; import { Formik } from 'formik'; import { fireEvent, render, waitFor, within } from 'test-helpers/test-utils'; import ProjectIUCNForm, { diff --git a/app/src/features/projects/components/ProjectIUCNForm.tsx b/app/src/features/projects/components/ProjectIUCNForm.tsx index 914eb19afa..0930995c2b 100644 --- a/app/src/features/projects/components/ProjectIUCNForm.tsx +++ b/app/src/features/projects/components/ProjectIUCNForm.tsx @@ -9,7 +9,7 @@ import InputLabel from '@mui/material/InputLabel'; import MenuItem from '@mui/material/MenuItem'; import Select from '@mui/material/Select'; import Typography from '@mui/material/Typography'; -import { IMultiAutocompleteFieldOption } from 'components/fields/MultiAutocompleteFieldVariableSize'; +import { IMultiAutocompleteFieldOption } from 'components/fields/MultiAutocompleteField'; import { FieldArray, FieldArrayRenderProps, useFormikContext } from 'formik'; import React from 'react'; import yup from 'utils/YupSchema'; diff --git a/app/src/features/projects/components/ProjectUserForm.test.tsx b/app/src/features/projects/components/ProjectUserForm.test.tsx index 6c2d80d026..1df102bccc 100644 --- a/app/src/features/projects/components/ProjectUserForm.test.tsx +++ b/app/src/features/projects/components/ProjectUserForm.test.tsx @@ -2,24 +2,22 @@ import { PROJECT_ROLE } from 'constants/roles'; import { AuthStateContext } from 'contexts/authStateContext'; import { Formik } from 'formik'; import { useBiohubApi } from 'hooks/useBioHubApi'; -import { ICode } from 'interfaces/useCodesApi.interface'; +import { IGetAllCodeSetsResponse } from 'interfaces/useCodesApi.interface'; import { ISystemUser } from 'interfaces/useUserApi.interface'; import { getMockAuthState, SystemAdminAuthState } from 'test-helpers/auth-helpers'; import { render, waitFor } from 'test-helpers/test-utils'; import ProjectUserForm, { ProjectUserRoleYupSchema } from './ProjectUserForm'; -const mockRoles: ICode[] = [ +const mockRoles: IGetAllCodeSetsResponse['project_roles'] = [ { id: 1, - name: PROJECT_ROLE.COLLABORATOR + name: 'Project Manager', + description: 'Manages the project' }, { id: 2, - name: PROJECT_ROLE.COORDINATOR - }, - { - id: 3, - name: PROJECT_ROLE.OBSERVER + name: 'Team Member', + description: 'Regular team member' } ]; diff --git a/app/src/features/projects/components/ProjectUserForm.tsx b/app/src/features/projects/components/ProjectUserForm.tsx index 10d7a1211a..8e4f07a393 100644 --- a/app/src/features/projects/components/ProjectUserForm.tsx +++ b/app/src/features/projects/components/ProjectUserForm.tsx @@ -6,7 +6,7 @@ import { SystemUserAutocompleteField } from 'components/fields/SystemUserAutocom import UserRoleSelector from 'components/user/UserRoleSelector'; import { PROJECT_ROLE } from 'constants/roles'; import { useFormikContext } from 'formik'; -import { ICode } from 'interfaces/useCodesApi.interface'; +import { IGetAllCodeSetsResponse } from 'interfaces/useCodesApi.interface'; import { ICreateProjectRequest, IGetProjectParticipant } from 'interfaces/useProjectApi.interface'; import { ISystemUser } from 'interfaces/useUserApi.interface'; import { TransitionGroup } from 'react-transition-group'; @@ -30,14 +30,15 @@ export const ProjectUserRoleYupSchema = yup.object().shape({ }); interface IProjectUserFormProps { - roles: ICode[]; + roles: IGetAllCodeSetsResponse['project_roles']; + description?: string; } export const ProjectUserRoleFormInitialValues = { participants: [] }; -const ProjectUserForm = (props: IProjectUserFormProps) => { +const ProjectUserForm: React.FC = (props) => { const { handleSubmit, values, setFieldValue, errors, setErrors } = useFormikContext(); const handleAddUser = (user: ISystemUser | IGetProjectParticipant) => { @@ -175,6 +176,7 @@ const ProjectUserForm = (props: IProjectUserFormProps) => { index={index} user={user} roles={props.roles} + description={props.description} error={error} selectedRole={getSelectedRole(index)} handleAdd={handleAddUserRole} diff --git a/app/src/features/projects/edit/EditProjectForm.tsx b/app/src/features/projects/edit/EditProjectForm.tsx index 021ecd5020..b5b268da2a 100644 --- a/app/src/features/projects/edit/EditProjectForm.tsx +++ b/app/src/features/projects/edit/EditProjectForm.tsx @@ -65,7 +65,9 @@ const EditProjectForm = } + component={ + + } /> diff --git a/app/src/features/surveys/components/methodology/PurposeAndMethodologyForm.tsx b/app/src/features/surveys/components/methodology/PurposeAndMethodologyForm.tsx index 17119f47d5..fc2e0b8cb1 100644 --- a/app/src/features/surveys/components/methodology/PurposeAndMethodologyForm.tsx +++ b/app/src/features/surveys/components/methodology/PurposeAndMethodologyForm.tsx @@ -1,10 +1,7 @@ import Box from '@mui/material/Box'; import Grid from '@mui/material/Grid'; import CustomTextField from 'components/fields/CustomTextField'; -import MultiAutocompleteField from 'components/fields/MultiAutocompleteField'; -import MultiAutocompleteFieldVariableSize, { - IMultiAutocompleteFieldOption -} from 'components/fields/MultiAutocompleteFieldVariableSize'; +import MultiAutocompleteField, { IMultiAutocompleteFieldOption } from 'components/fields/MultiAutocompleteField'; import { ISelectWithSubtextFieldOption } from 'components/fields/SelectWithSubtext'; import React from 'react'; import yup from 'utils/YupSchema'; @@ -48,7 +45,7 @@ const PurposeAndMethodologyForm: React.FC = (pr - { +const SurveyUserForm: React.FC = (props) => { const { handleSubmit, values, setFieldValue, errors, setErrors } = useFormikContext(); const handleAddUser = (user: ISystemUser | IGetSurveyParticipant) => { diff --git a/app/src/features/surveys/components/sampling-strategy/SurveySiteSelectionForm.tsx b/app/src/features/surveys/components/sampling-strategy/SurveySiteSelectionForm.tsx index 5add2e88d3..f0015cbba7 100644 --- a/app/src/features/surveys/components/sampling-strategy/SurveySiteSelectionForm.tsx +++ b/app/src/features/surveys/components/sampling-strategy/SurveySiteSelectionForm.tsx @@ -65,7 +65,7 @@ const SurveySiteSelectionForm = (props: ISurveySiteSelectionFormProps) => { assert(codesContext.codesDataLoader.data); const siteStrategies = codesContext.codesDataLoader.data.site_selection_strategies.map((code) => { - return { label: code.name, value: code.name }; + return { label: code.name, value: code.name, description: code.description }; }); const selectedSiteStrategies = siteStrategies.filter((item) => values.site_selection.strategies.includes(item.value)); diff --git a/app/src/features/surveys/edit/EditSurveyForm.tsx b/app/src/features/surveys/edit/EditSurveyForm.tsx index 8b26b90f7f..a486949be5 100644 --- a/app/src/features/surveys/edit/EditSurveyForm.tsx +++ b/app/src/features/surveys/edit/EditSurveyForm.tsx @@ -14,6 +14,7 @@ import SurveyPartnershipsForm, { SurveyPartnershipsFormYupSchema } from 'features/surveys/view/components/SurveyPartnershipsForm'; import { Formik, FormikProps } from 'formik'; +import { IGetAllCodeSetsResponse } from 'interfaces/useCodesApi.interface'; import { ICreateSurveyRequest, IUpdateSurveyRequest } from 'interfaces/useSurveyApi.interface'; import React, { useContext, useEffect } from 'react'; import AgreementsForm, { AgreementsYupSchema } from '../components/agreements/AgreementsForm'; @@ -80,6 +81,14 @@ const EditSurveyForm = < .concat(SurveyPartnershipsFormYupSchema) .concat(SpeciesYupSchema); + // Add this transformer function + const transformSurveyJobs = (jobs: typeof codes.survey_jobs): IGetAllCodeSetsResponse['project_roles'] => { + return jobs.map((job) => ({ + ...job, + description: job.description + })); + }; + return ( innerRef={props.formikRef} @@ -97,7 +106,7 @@ const EditSurveyForm = < { - return { value: item.id, label: item.name, subText: item.description }; + return { value: item.id, label: item.name, description: item.description }; }) || [] } /> @@ -150,12 +159,12 @@ const EditSurveyForm = < { - return { value: item.id, label: item.name, subText: item.description }; + return { value: item.id, label: item.name, description: item.description }; }) || [] } type={ codes?.type?.map((item) => { - return { value: item.id, label: item.name }; + return { value: item.id, label: item.name, description: item.description }; }) || [] } /> @@ -166,7 +175,7 @@ const EditSurveyForm = < } + component={} /> diff --git a/app/src/features/surveys/view/components/SurveyPartnershipsForm.tsx b/app/src/features/surveys/view/components/SurveyPartnershipsForm.tsx index b868a350f2..bc628a25e7 100644 --- a/app/src/features/surveys/view/components/SurveyPartnershipsForm.tsx +++ b/app/src/features/surveys/view/components/SurveyPartnershipsForm.tsx @@ -1,7 +1,7 @@ import Grid from '@mui/material/Grid'; -import MultiAutocompleteFieldVariableSize, { - IMultiAutocompleteFieldOption -} from 'components/fields/MultiAutocompleteFieldVariableSize'; +import { IMultiAutocompleteFieldOption } from 'components/fields/MultiAutocompleteField'; +import MultiAutocompleteFieldVariableSize from 'components/fields/MultiAutocompleteFieldVariableSize'; + import { CodesContext } from 'contexts/codesContext'; import { useFormikContext } from 'formik'; import { useContext, useEffect } from 'react'; diff --git a/app/src/hooks/api/useUserApi.test.ts b/app/src/hooks/api/useUserApi.test.ts index d2686a1f1e..d5cd8e98d7 100644 --- a/app/src/hooks/api/useUserApi.test.ts +++ b/app/src/hooks/api/useUserApi.test.ts @@ -45,31 +45,45 @@ describe('useUserApi', () => { expect(result.role_names).toEqual(['role 1', 'role 2']); }); + // Update the test to match the correct interface it('getUsersList works as expected', async () => { - mock.onGet('/api/user/list').reply(200, [ - { - system_user_id: 1, - user_identifier: 'myidirboss', - role_names: ['role 1', 'role 2'] - }, - { - system_user_id: 2, - user_identifier: 'myidirbossagain', - role_names: ['role 1', 'role 4'] + // ...existing test setup... + + const mockResponse = { + users: [ + { + system_user_id: 1, + user_identifier: 'myidirboss', + role_names: ['role 1', 'role 2'] + // ... other user properties + }, + { + system_user_id: 2 + // ... second user properties + } + ], + pagination: { + total: 2, + current_page: 1, + last_page: 1, + per_page: 10 } - ]); + }; + + // Mock axios response + mock.onGet('/api/user/list').reply(200, mockResponse); const result = await useUserApi(axios).getUsersList( {}, { page: 0, limit: 10, sort: 'system_user_id', order: 'desc' } ); - expect(result[0].system_user_id).toEqual(1); - expect(result[0].user_identifier).toEqual('myidirboss'); - expect(result[0].role_names).toEqual(['role 1', 'role 2']); - expect(result[1].system_user_id).toEqual(2); - expect(result[1].user_identifier).toEqual('myidirbossagain'); - expect(result[1].role_names).toEqual(['role 1', 'role 4']); + expect(result.users[0].system_user_id).toEqual(1); + expect(result.users[0].user_identifier).toEqual('myidirboss'); + expect(result.users[0].role_names).toEqual(['role 1', 'role 2']); + expect(result.users[1].system_user_id).toEqual(2); + expect(result.pagination.total).toEqual(2); + expect(result.pagination.current_page).toEqual(1); }); it('getProjectList works as expected', async () => { diff --git a/app/src/interfaces/useCodesApi.interface.ts b/app/src/interfaces/useCodesApi.interface.ts index 090cad24dd..4119804bd7 100644 --- a/app/src/interfaces/useCodesApi.interface.ts +++ b/app/src/interfaces/useCodesApi.interface.ts @@ -25,17 +25,17 @@ export interface IGetAllCodeSetsResponse { first_nations: CodeSet; agency: CodeSet; investment_action_category: CodeSet<{ id: number; agency_id: number; name: string }>; - type: CodeSet; + type: CodeSet<{ id: number; name: string; description: string }>; proprietor_type: CodeSet<{ id: number; name: string; is_first_nation: boolean }>; iucn_conservation_action_level_1_classification: CodeSet; iucn_conservation_action_level_2_subclassification: CodeSet<{ id: number; iucn1_id: number; name: string }>; iucn_conservation_action_level_3_subclassification: CodeSet<{ id: number; iucn2_id: number; name: string }>; system_roles: CodeSet; - project_roles: CodeSet; + project_roles: CodeSet<{ id: number; name: string; description: string }>; administrative_activity_status_type: CodeSet; intended_outcomes: CodeSet<{ id: number; name: string; description: string }>; - survey_jobs: CodeSet; - site_selection_strategies: CodeSet; + survey_jobs: CodeSet<{ id: number; name: string; description: string }>; + site_selection_strategies: CodeSet<{ id: number; name: string; description: string }>; survey_progress: CodeSet<{ id: number; name: string; description: string }>; sample_methods: CodeSet<{ id: number; name: string; description: string }>; method_response_metrics: CodeSet<{ id: number; name: string; description: string }>; diff --git a/app/src/interfaces/useUserApi.interface.ts b/app/src/interfaces/useUserApi.interface.ts index fe63757bdc..606db44b5d 100644 --- a/app/src/interfaces/useUserApi.interface.ts +++ b/app/src/interfaces/useUserApi.interface.ts @@ -6,8 +6,8 @@ export interface ISystemUser { user_guid: string | null; identity_source: string; record_end_date: string | null; - role_ids: [number] | []; - role_names: [string] | []; + role_ids: number[]; + role_names: string[]; email: string; display_name: string; agency: string | null; diff --git a/app/src/test-helpers/code-helpers.ts b/app/src/test-helpers/code-helpers.ts index 28c5e87504..9444f25323 100644 --- a/app/src/test-helpers/code-helpers.ts +++ b/app/src/test-helpers/code-helpers.ts @@ -5,7 +5,7 @@ export const codes: IGetAllCodeSetsResponse = { first_nations: [{ id: 1, name: 'First nations code' }], agency: [{ id: 1, name: 'Funding source code' }], investment_action_category: [{ id: 1, agency_id: 1, name: 'Investment action category' }], - type: [{ id: 1, name: 'Type code' }], + type: [{ id: 1, name: 'Type code', description: 'Type code description' }], proprietor_type: [ { id: 1, name: 'Proprietor code 1', is_first_nation: false }, { id: 2, name: 'First Nations Land', is_first_nation: true } @@ -27,8 +27,8 @@ export const codes: IGetAllCodeSetsResponse = { { id: 2, name: 'Role 2' } ], project_roles: [ - { id: 1, name: 'Project Role 1' }, - { id: 2, name: 'Project Role 2' } + { id: 1, name: 'Project Role 1', description: 'Description 1' }, + { id: 2, name: 'Project Role 2', description: 'Description 2' } ], administrative_activity_status_type: [ { id: 1, name: 'Pending' }, @@ -40,12 +40,12 @@ export const codes: IGetAllCodeSetsResponse = { { id: 2, name: 'Intended Outcome 2', description: 'Description 2' } ], survey_jobs: [ - { id: 1, name: 'Survey Job 1' }, - { id: 2, name: 'Survey Job 2' } + { id: 1, name: 'Survey Job 1', description: 'Description 1' }, + { id: 2, name: 'Survey Job 2', description: 'Description 2' } ], site_selection_strategies: [ - { id: 1, name: 'Strategy 1' }, - { id: 2, name: 'Strategy 2' } + { id: 1, name: 'Strategy 1', description: 'Description 1' }, + { id: 2, name: 'Strategy 2', description: 'Description 2' } ], sample_methods: [ { id: 1, name: 'Camera Trap', description: 'Description 1' }, diff --git a/app/tsconfig.json b/app/tsconfig.json index a156d42a62..4483e2b35c 100644 --- a/app/tsconfig.json +++ b/app/tsconfig.json @@ -12,7 +12,6 @@ "forceConsistentCasingInFileNames": true, "noImplicitThis": true, "noImplicitAny": true, - "suppressImplicitAnyIndexErrors": true, "allowSyntheticDefaultImports": true, "noUnusedLocals": false, "esModuleInterop": true, diff --git a/database/src/migrations/20250128000001_update_type_descriptions.ts b/database/src/migrations/20250128000001_update_type_descriptions.ts new file mode 100644 index 0000000000..6103d59091 --- /dev/null +++ b/database/src/migrations/20250128000001_update_type_descriptions.ts @@ -0,0 +1,46 @@ +import { Knex } from 'knex'; + +/** + * Add new columns to survey_sample_period table + * + * @export + * @param {Knex} knex + * @return {*} {Promise} + */ +export async function up(knex: Knex): Promise { + await knex.raw(` + +SET search_path=biohub; + +---------------------------------------------------------------------------------------- +-- Add new type descriptions to the type table +---------------------------------------------------------------------------------------- + +UPDATE type + SET description = CASE name + WHEN 'Telemetry' THEN 'Tracking animal movements using radio, GPS, or other remote sensing technologies.' + WHEN 'Species observations' THEN 'Recording the presence, behavior, or abundance of animals in the survey area.' + WHEN 'Animal captures' THEN 'Physically capturing animals for tagging, measurement, or sample collection.' + WHEN 'Animal mortalities' THEN 'Documenting dead animals, including cause of death when possible.' + WHEN 'Habitat features' THEN 'Recording characteristics of the environment, such as vegetation, water sources, or terrain.' + END + WHERE name IN ('Telemetry', 'Species observations', 'Animal captures', 'Animal mortalities', 'Habitat features'); + + +---------------------------------------------------------------------------------------- +-- Add new site_selection_strategy descriptions to the site_strategy table +---------------------------------------------------------------------------------------- +UPDATE site_strategy + SET description = CASE name + WHEN 'Random' THEN 'Randomly selecting sites for surveying.' + WHEN 'Stratified' THEN 'Dividing the survey area into distinct sub-areas and sampling each sub-area separately.' + WHEN 'Systematic' THEN 'Selecting sites at regular intervals across the survey area.' + END + WHERE name IN ('Random', 'Stratified', 'Systematic'); + +`); +} + +export async function down(knex: Knex): Promise { + await knex.raw(``); +}