Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Updating standards page to include marking information #1501

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions api/src/models/standards-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export const EnvironmentStandardsSchema = z.object({

export type EnvironmentStandards = z.infer<typeof EnvironmentStandardsSchema>;

export interface MarkingStandards {
types: { name: string; marking_type_id: string; description: string }[];
colours: { colour: string; colour_id: string; description: string }[];
}

export const MethodStandardSchema = z.object({
method_lookup_id: z.number(),
name: z.string(),
Expand Down
51 changes: 51 additions & 0 deletions api/src/openapi/schemas/standards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,54 @@ export const MethodStandardSchema: OpenAPIV3.SchemaObject = {
}
}
};

export const MarkingStandardsSchema: OpenAPIV3.SchemaObject = {
type: 'object',
description: 'Marking standards response object showing supported marking types and colours',
additionalProperties: false,
properties: {
types: {
type: 'array',
description: 'Array of marking types',
items: {
type: 'object',
properties: {
name: {
type: 'string',
description: 'Name of the marking type'
},
marking_type_id: {
type: 'string',
description: 'ID of the marking type'
},
description: {
type: 'string',
description: 'Description of the marking type',
nullable: true
}
}
}
},
colours: {
type: 'array',
description: 'Array of marking colour options',
items: {
type: 'object',
properties: {
colour: {
type: 'string',
description: 'Name of the marking colour'
},
colour_id: {
type: 'string',
description: 'ID of the marking colour'
},
description: {
type: 'string',
description: 'description of the marking colour'
}
}
}
}
}
};
80 changes: 80 additions & 0 deletions api/src/paths/standards/markings/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { RequestHandler } from 'express';
import { Operation } from 'express-openapi';
import { getAPIUserDBConnection } from '../../../database/db';
import { MarkingStandardsSchema } from '../../../openapi/schemas/standards';
import { StandardsService } from '../../../services/standards-service';
import { getLogger } from '../../../utils/logger';

const defaultLog = getLogger('paths/projects');

Check warning on line 8 in api/src/paths/standards/markings/index.ts

View check run for this annotation

Codecov / codecov/patch

api/src/paths/standards/markings/index.ts#L8

Added line #L8 was not covered by tests

export const GET: Operation = [getMarkingStandards()];

Check warning on line 10 in api/src/paths/standards/markings/index.ts

View check run for this annotation

Codecov / codecov/patch

api/src/paths/standards/markings/index.ts#L10

Added line #L10 was not covered by tests

GET.apiDoc = {

Check warning on line 12 in api/src/paths/standards/markings/index.ts

View check run for this annotation

Codecov / codecov/patch

api/src/paths/standards/markings/index.ts#L12

Added line #L12 was not covered by tests
description: 'Gets lookup values for marking variables',
tags: ['standards'],
parameters: [
{
in: 'query',
name: 'keyword',
required: false,
schema: {
type: 'string',
nullable: true
}
}
],
responses: {
200: {
description: 'Marking data standards response object.',
content: {
'application/json': {
schema: MarkingStandardsSchema
}
}
},
400: {
$ref: '#/components/responses/400'
},
401: {
$ref: '#/components/responses/401'
},
403: {
$ref: '#/components/responses/403'
},
500: {
$ref: '#/components/responses/500'
},
default: {
$ref: '#/components/responses/default'
}
}
};

/**
* Get marking data standards
*
* @returns {RequestHandler}
*/
export function getMarkingStandards(): RequestHandler {
return async (_, res) => {
const connection = getAPIUserDBConnection();

Check warning on line 60 in api/src/paths/standards/markings/index.ts

View check run for this annotation

Codecov / codecov/patch

api/src/paths/standards/markings/index.ts#L59-L60

Added lines #L59 - L60 were not covered by tests

try {
await connection.open();

Check warning on line 63 in api/src/paths/standards/markings/index.ts

View check run for this annotation

Codecov / codecov/patch

api/src/paths/standards/markings/index.ts#L62-L63

Added lines #L62 - L63 were not covered by tests

const standardsService = new StandardsService(connection);

Check warning on line 65 in api/src/paths/standards/markings/index.ts

View check run for this annotation

Codecov / codecov/patch

api/src/paths/standards/markings/index.ts#L65

Added line #L65 was not covered by tests

const response = await standardsService.getMarkingStandards();

Check warning on line 67 in api/src/paths/standards/markings/index.ts

View check run for this annotation

Codecov / codecov/patch

api/src/paths/standards/markings/index.ts#L67

Added line #L67 was not covered by tests

await connection.commit();

Check warning on line 69 in api/src/paths/standards/markings/index.ts

View check run for this annotation

Codecov / codecov/patch

api/src/paths/standards/markings/index.ts#L69

Added line #L69 was not covered by tests

return res.status(200).json(response);

Check warning on line 71 in api/src/paths/standards/markings/index.ts

View check run for this annotation

Codecov / codecov/patch

api/src/paths/standards/markings/index.ts#L71

Added line #L71 was not covered by tests
} catch (error) {
defaultLog.error({ label: 'getMarkingStandards', message: 'error', error });
connection.rollback();
throw error;

Check warning on line 75 in api/src/paths/standards/markings/index.ts

View check run for this annotation

Codecov / codecov/patch

api/src/paths/standards/markings/index.ts#L73-L75

Added lines #L73 - L75 were not covered by tests
} finally {
connection.release();

Check warning on line 77 in api/src/paths/standards/markings/index.ts

View check run for this annotation

Codecov / codecov/patch

api/src/paths/standards/markings/index.ts#L77

Added line #L77 was not covered by tests
}
};
}
21 changes: 20 additions & 1 deletion api/src/services/standards-service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IDBConnection } from '../database/db';
import { EnvironmentStandards, ISpeciesStandards, MethodStandard } from '../models/standards-view';
import { EnvironmentStandards, ISpeciesStandards, MarkingStandards, MethodStandard } from '../models/standards-view';
import { StandardsRepository } from '../repositories/standards-repository';
import { CritterbaseService } from './critterbase-service';
import { DBService } from './db-service';
Expand Down Expand Up @@ -50,6 +50,25 @@
};
}

/**
* Gets marking standards
*
* @return {MarkingStandards}
* @memberof standardsService
*/
async getMarkingStandards(): Promise<MarkingStandards> {
const types = await this.critterbaseService.getMarkingTypes();
const colours = await this.critterbaseService.getColours();
return {

Check warning on line 62 in api/src/services/standards-service.ts

View check run for this annotation

Codecov / codecov/patch

api/src/services/standards-service.ts#L60-L62

Added lines #L60 - L62 were not covered by tests
types: types.map((type) => {
return { name: type.key, marking_type_id: type.id, description: type.value };

Check warning on line 64 in api/src/services/standards-service.ts

View check run for this annotation

Codecov / codecov/patch

api/src/services/standards-service.ts#L64

Added line #L64 was not covered by tests
}),
colours: colours.map((colour) => {
return { colour: colour.value, colour_id: colour.id, description: colour.key };

Check warning on line 67 in api/src/services/standards-service.ts

View check run for this annotation

Codecov / codecov/patch

api/src/services/standards-service.ts#L67

Added line #L67 was not covered by tests
})
};
}

/**
* Gets environment standards
*
Expand Down
12 changes: 9 additions & 3 deletions app/src/features/standards/StandardsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { mdiLeaf, mdiPaw, mdiToolbox } from '@mdi/js';
import { mdiLeaf, mdiPaw, mdiTag, mdiToolbox } from '@mdi/js';
import Box from '@mui/material/Box';
import { grey } from '@mui/material/colors';
import Container from '@mui/material/Container';
Expand All @@ -11,13 +11,15 @@ import { SystemAlertBanner } from 'features/alert/banner/SystemAlertBanner';
import { SystemAlertBannerEnum } from 'interfaces/useAlertApi.interface';
import { useState } from 'react';
import { EnvironmentStandards } from './view/environment/EnvironmentStandards';
import { MarkingStandards } from './view/markings/MarkingStandards';
import { MethodStandards } from './view/methods/MethodStandards';
import { SpeciesStandards } from './view/species/SpeciesStandards';

export enum StandardsPageView {
SPECIES = 'SPECIES',
METHODS = 'METHODS',
ENVIRONMENT = 'ENVIRONMENT'
ENVIRONMENT = 'ENVIRONMENT',
MARKINGS = 'MARKINGS'
}

const StandardsPage = () => {
Expand All @@ -26,7 +28,8 @@ const StandardsPage = () => {
const views = [
{ value: StandardsPageView.SPECIES, label: 'Species', icon: mdiPaw },
{ value: StandardsPageView.METHODS, label: 'Sampling Methods', icon: mdiToolbox },
{ value: StandardsPageView.ENVIRONMENT, label: 'Environment variables', icon: mdiLeaf }
{ value: StandardsPageView.ENVIRONMENT, label: 'Environment variables', icon: mdiLeaf },
{ value: StandardsPageView.MARKINGS, label: 'Markings', icon: mdiTag }
];

return (
Expand Down Expand Up @@ -56,6 +59,9 @@ const StandardsPage = () => {

{/* ENVIRONMENT STANDARDS */}
{activeView === StandardsPageView.ENVIRONMENT && <EnvironmentStandards />}

{/* MARKING TYPE STANDARDS */}
{activeView === StandardsPageView.MARKINGS && <MarkingStandards />}
</Box>
</Stack>
</Container>
Expand Down
44 changes: 44 additions & 0 deletions app/src/features/standards/view/markings/MarkingStandards.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Box, Skeleton, Stack, Typography } from '@mui/material';
import { LoadingGuard } from 'components/loading/LoadingGuard';
import { useBiohubApi } from 'hooks/useBioHubApi';
import useDataLoader from 'hooks/useDataLoader';
import { useEffect } from 'react';
import { MarkingStandardsResults } from './MarkingStandardsResults';

export const MarkingStandards = () => {
const biohubApi = useBiohubApi();

Check warning on line 9 in app/src/features/standards/view/markings/MarkingStandards.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/features/standards/view/markings/MarkingStandards.tsx#L8-L9

Added lines #L8 - L9 were not covered by tests

const markingsDataLoader = useDataLoader((keyword?: string) => biohubApi.standards.getMarkingsStandards(keyword));

Check warning on line 11 in app/src/features/standards/view/markings/MarkingStandards.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/features/standards/view/markings/MarkingStandards.tsx#L11

Added line #L11 was not covered by tests

useEffect(() => {
markingsDataLoader.load();

Check warning on line 14 in app/src/features/standards/view/markings/MarkingStandards.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/features/standards/view/markings/MarkingStandards.tsx#L13-L14

Added lines #L13 - L14 were not covered by tests
}, [markingsDataLoader]);

if (!markingsDataLoader.data) {
return <></>;

Check warning on line 18 in app/src/features/standards/view/markings/MarkingStandards.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/features/standards/view/markings/MarkingStandards.tsx#L18

Added line #L18 was not covered by tests
}

return (

Check warning on line 21 in app/src/features/standards/view/markings/MarkingStandards.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/features/standards/view/markings/MarkingStandards.tsx#L21

Added line #L21 was not covered by tests
<Box my={2}>
<LoadingGuard
isLoading={markingsDataLoader.isLoading || !markingsDataLoader.isReady}
isLoadingFallback={
<Stack gap={2}>
<Skeleton variant="rectangular" height="56px" sx={{ borderRadius: '5px' }} />
<Skeleton variant="rectangular" height="56px" sx={{ borderRadius: '5px' }} />
</Stack>
}
hasNoData={
!(markingsDataLoader.data?.types.length || markingsDataLoader.data?.colours.length) &&
markingsDataLoader.isReady
}
hasNoDataFallback={
<Box minHeight="200px" display="flex" alignItems="center" justifyContent="center">
<Typography color="textSecondary">No marking standards found</Typography>
</Box>
}>
<MarkingStandardsResults standards={markingsDataLoader.data} />
</LoadingGuard>
</Box>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { grey } from '@mui/material/colors';
import Stack from '@mui/material/Stack';
import { AccordionStandardCard } from 'features/standards/view/components/AccordionStandardCard';
import { IMarkingsStandards } from 'interfaces/useStandardsApi.interface';

interface IMarkingStandardsResultsProps {
standards: IMarkingsStandards;
}

/**
* Component to display marking standards results
*
* @return {*}
*/
export const MarkingStandardsResults = (props: IMarkingStandardsResultsProps) => {
const { standards } = props;

Check warning on line 16 in app/src/features/standards/view/markings/MarkingStandardsResults.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/features/standards/view/markings/MarkingStandardsResults.tsx#L15-L16

Added lines #L15 - L16 were not covered by tests

if (!standards || !(standards.types.length || standards.colours.length)) {
// No standards to display
return null;

Check warning on line 20 in app/src/features/standards/view/markings/MarkingStandardsResults.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/features/standards/view/markings/MarkingStandardsResults.tsx#L20

Added line #L20 was not covered by tests
}

return (

Check warning on line 23 in app/src/features/standards/view/markings/MarkingStandardsResults.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/features/standards/view/markings/MarkingStandardsResults.tsx#L23

Added line #L23 was not covered by tests
<Stack gap={2}>
{/* Accordion for Marking Types */}
{standards.types.length > 0 && (
<AccordionStandardCard label="Marking Types" colour={grey[100]}>
<Stack gap={2} my={2}>
{standards.types.map((type) => (
<AccordionStandardCard key={type.name} label={type.description} colour={grey[200]} />

Check warning on line 30 in app/src/features/standards/view/markings/MarkingStandardsResults.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/features/standards/view/markings/MarkingStandardsResults.tsx#L30

Added line #L30 was not covered by tests
))}
</Stack>
</AccordionStandardCard>
)}

{/* Accordion for Marking Colours */}
{standards.colours.length > 0 && (
<AccordionStandardCard label="Marking Colours" colour={grey[100]}>
<Stack gap={2} my={2}>
{standards.colours.map((colour) => (
<AccordionStandardCard key={colour.colour} label={colour.colour} colour={grey[200]} />

Check warning on line 41 in app/src/features/standards/view/markings/MarkingStandardsResults.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/features/standards/view/markings/MarkingStandardsResults.tsx#L41

Added line #L41 was not covered by tests
))}
</Stack>
</AccordionStandardCard>
)}
</Stack>
);
};
27 changes: 25 additions & 2 deletions app/src/hooks/api/useStandardsApi.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { AxiosInstance } from 'axios';
import { IEnvironmentStandards, IMethodStandard, ISpeciesStandards } from 'interfaces/useStandardsApi.interface';
import {
IEnvironmentStandards,
IMarkingsStandards,
IMethodStandard,
ISpeciesStandards
} from 'interfaces/useStandardsApi.interface';
import qs from 'qs';

/**
Expand Down Expand Up @@ -55,10 +60,28 @@
return data;
};

/**
* Fetch markings
*
* @param {string} keyword
* @return {*} {Promise<IMarkingsStandards>}
*/
const getMarkingsStandards = async (keyword?: string): Promise<IMarkingsStandards> => {
const params = { keyword };

Check warning on line 70 in app/src/hooks/api/useStandardsApi.ts

View check run for this annotation

Codecov / codecov/patch

app/src/hooks/api/useStandardsApi.ts#L70

Added line #L70 was not covered by tests

const { data } = await axios.get('/api/standards/markings', {

Check warning on line 72 in app/src/hooks/api/useStandardsApi.ts

View check run for this annotation

Codecov / codecov/patch

app/src/hooks/api/useStandardsApi.ts#L72

Added line #L72 was not covered by tests
params,
paramsSerializer: (params) => qs.stringify(params)

Check warning on line 74 in app/src/hooks/api/useStandardsApi.ts

View check run for this annotation

Codecov / codecov/patch

app/src/hooks/api/useStandardsApi.ts#L74

Added line #L74 was not covered by tests
});

return data;

Check warning on line 77 in app/src/hooks/api/useStandardsApi.ts

View check run for this annotation

Codecov / codecov/patch

app/src/hooks/api/useStandardsApi.ts#L77

Added line #L77 was not covered by tests
};

return {
getSpeciesStandards,
getEnvironmentStandards,
getMethodStandards
getMethodStandards,
getMarkingsStandards
};
};

Expand Down
12 changes: 12 additions & 0 deletions app/src/interfaces/useStandardsApi.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
CBQuantitativeMeasurementTypeDefinition,
ICollectionUnit
} from './useCritterApi.interface';
import { IMarkingColourOption, IMarkingTypeResponse } from './useMarkingApi.interface';

interface IStandardNameDescription {
name: string;
Expand Down Expand Up @@ -59,3 +60,14 @@ export interface IEnvironmentStandards {
qualitative: IQualitativeAttributeStandard[];
quantitative: IQuantitativeAttributeStandard[];
}

/**
* Data standards for markings
*
* @export
* @interface IMarkingsStandards
*/
export interface IMarkingsStandards {
types: IMarkingTypeResponse[];
colours: IMarkingColourOption[];
}
Loading