Skip to content

Commit

Permalink
feat(anni): resolve bricks & reorganize db helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
jannis-baum committed Jul 3, 2022
1 parent a52303c commit 6a5e82a
Show file tree
Hide file tree
Showing 15 changed files with 143 additions and 39 deletions.
1 change: 1 addition & 0 deletions annotation-interface/common/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const supportedLanguages = ['English', 'German'] as const;
export type SupportedLanguage = typeof supportedLanguages[number];
export const pharMeLanguage: SupportedLanguage = 'English';

export const brickUsages = [
'Drug class',
Expand Down
9 changes: 6 additions & 3 deletions annotation-interface/components/bricks/AutocompleteArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ import AutocompleteMenu, { AutoCompleteMenuRef } from './AutocompleteMenu';
type Props = {
value: string;
onChange: (text: string) => void;
validPlaceholders: string[];
};

const validPlaceholders = ['drug-name', 'gene-symbol', 'gene-result'];

const AutocompleteArea = ({ value: text, onChange: setText }: Props) => {
const AutocompleteArea = ({
value: text,
onChange: setText,
validPlaceholders,
}: Props) => {
const [selection, setSelection] = useState<
[start: number, end: number] | null
>(null);
Expand Down
15 changes: 13 additions & 2 deletions annotation-interface/components/bricks/BrickForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@ import {
supportedLanguages,
} from '../../common/constants';
import {
ITextBrick,
ITextBrickTranslation,
translationIsValid,
translationsToArray,
translationsToMap,
} from '../../database/helpers/brick-translations';
import {
allBrickPlaceholders,
medicationBrickPlaceholders,
} from '../../database/helpers/resolve-bricks';
import {
ITextBrick,
ITextBrickTranslation,
} from '../../database/models/TextBrick';
import SelectionPopover from '../common/SelectionPopover';
import WithIcon from '../common/WithIcon';
Expand Down Expand Up @@ -120,6 +126,11 @@ const BrickForm = ({ usage, brick }: Props) => {
onChange={(text) =>
updateTranslation(language, text)
}
validPlaceholders={
usage.startsWith('Drug')
? [...medicationBrickPlaceholders]
: [...allBrickPlaceholders]
}
/>
</div>
))}
Expand Down
29 changes: 29 additions & 0 deletions annotation-interface/database/helpers/brick-translations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { SupportedLanguage } from '../../common/constants';
import { ITextBrickTranslation } from '../models/TextBrick';
import { OptionalId } from './types';

export function translationsToMap<IdT extends OptionalId = undefined>(
translations: ITextBrickTranslation<IdT>[],
): Map<SupportedLanguage, string> {
const map = new Map<SupportedLanguage, string>();
if (translations) {
translations.forEach((translation) =>
map.set(translation.language, translation.text),
);
}
return map;
}

export function translationsToArray(
translations: Map<SupportedLanguage, string>,
): ITextBrickTranslation[] {
return Array.from(translations.entries()).map(([language, text]) => {
return { language, text };
});
}

export function translationIsValid<IdT extends OptionalId = undefined>(
translation: ITextBrickTranslation<IdT>,
): boolean {
return translation.text.length > 0;
}
File renamed without changes.
85 changes: 85 additions & 0 deletions annotation-interface/database/helpers/resolve-bricks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { FilterQuery, Types } from 'mongoose';

import { pharMeLanguage, SupportedLanguage } from '../../common/constants';
import {
ServerGuidelineOverview,
ServerMedication,
} from '../../common/server-types';
import { IGuidelineAnnotation } from '../models/GuidelineAnnotation';
import { IMedAnnotation } from '../models/MedAnnotation';
import TextBrick, { ITextBrick } from '../models/TextBrick';
import { translationsToMap } from './brick-translations';
import { MongooseId, OptionalId } from './types';

export const medicationBrickPlaceholders = ['drug-name'] as const;
export const allBrickPlaceholders = [
...medicationBrickPlaceholders,
'gene-symbol',
'gene-result',
] as const;
type BrickPlaceholderValues = {
[Property in typeof allBrickPlaceholders[number]]?: string;
};

type BrickResolver =
| { from: 'medAnnotation'; with: IMedAnnotation<MongooseId> }
| { from: 'serverMedication'; with: ServerMedication }
| { from: 'guidelineAnnotation'; with: IGuidelineAnnotation<MongooseId> }
| { from: 'serverGuideline'; with: ServerGuidelineOverview };

const getPlaceholders = ({
from: type,
with: resolver,
}: BrickResolver): BrickPlaceholderValues => {
switch (type) {
case 'medAnnotation':
return { 'drug-name': resolver.medicationName };
case 'serverMedication':
return { 'drug-name': resolver.name };
case 'guidelineAnnotation':
return {
'drug-name': resolver.medicationName,
'gene-symbol': resolver.geneSymbol,
'gene-result': resolver.geneResult,
};
case 'serverGuideline':
return {
'drug-name': resolver.medication.name,
'gene-symbol': resolver.phenotype.geneSymbol.name,
'gene-result': resolver.phenotype.geneResult.name,
};
}
};

export type ResolvedBrick<IdT extends OptionalId> = [
_id: IdT,
text: string | undefined,
];

export function resolveBricks<IdT extends OptionalId>(
resolver: BrickResolver,
bricks: ITextBrick<IdT>[],
language: SupportedLanguage = pharMeLanguage,
): ResolvedBrick<IdT>[] {
const placeholders = getPlaceholders(resolver);
const resolved = bricks.map(({ _id, translations }) => {
let text = translationsToMap(translations).get(language);
if (text) {
Object.entries(placeholders).forEach(([placeholder, replace]) => {
text = text!.replaceAll(`#${placeholder}`, replace);
});
}
return [_id, text] as ResolvedBrick<IdT>;
});

return resolved;
}

export const findResolvedBricks = async (
resolver: BrickResolver,
filter: FilterQuery<ITextBrick<MongooseId>>,
language: SupportedLanguage = pharMeLanguage,
): Promise<ResolvedBrick<Types.ObjectId>[]> => {
const bricks = await TextBrick!.find(filter).lean().exec();
return resolveBricks(resolver, bricks, language);
};
File renamed without changes.
2 changes: 1 addition & 1 deletion annotation-interface/database/models/AbstractAnnotation.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import mongoose, { SchemaValidator, Types } from 'mongoose';

import { BrickUsage } from '../../common/constants';
import { IBaseModel, OptionalId } from '../types';
import { IBaseModel, OptionalId } from '../helpers/types';
import TextBrick from './TextBrick';

export interface IAbstractAnnotation<IdT extends OptionalId = undefined>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import mongoose, { Types } from 'mongoose';

import { MongooseId, OptionalId } from '../types';
import { MongooseId, OptionalId } from '../helpers/types';
import AbstractAnnotation, {
annotationBrickValidators,
IAbstractAnnotation,
Expand Down
2 changes: 1 addition & 1 deletion annotation-interface/database/models/MedAnnotation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import mongoose, { Types } from 'mongoose';

import { MongooseId, OptionalId } from '../types';
import { MongooseId, OptionalId } from '../helpers/types';
import AbstractAnnotation, {
annotationBrickValidators,
IAbstractAnnotation,
Expand Down
29 changes: 2 additions & 27 deletions annotation-interface/database/models/TextBrick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
BrickUsage,
supportedLanguages,
} from '../../common/constants';
import { IBaseModel, OptionalId } from '../types';
import { translationIsValid } from '../helpers/brick-translations';
import { IBaseModel, OptionalId } from '../helpers/types';

export interface ITextBrickTranslation<IdT extends OptionalId = undefined>
extends IBaseModel<IdT> {
Expand All @@ -20,32 +21,6 @@ export interface ITextBrick<IdT extends OptionalId = undefined>
translations: ITextBrickTranslation<IdT>[];
}

export function translationsToMap<IdT extends OptionalId = undefined>(
translations: ITextBrickTranslation<IdT>[],
): Map<SupportedLanguage, string> {
const map = new Map<SupportedLanguage, string>();
if (translations) {
translations.forEach((translation) =>
map.set(translation.language, translation.text),
);
}
return map;
}

export function translationsToArray(
translations: Map<SupportedLanguage, string>,
): ITextBrickTranslation[] {
return Array.from(translations.entries()).map(([language, text]) => {
return { language, text };
});
}

export function translationIsValid<IdT extends OptionalId = undefined>(
translation: ITextBrickTranslation<IdT>,
): boolean {
return translation.text.length > 0;
}

// prevent client side from trying to use node module
export default !mongoose.models
? undefined
Expand Down
2 changes: 1 addition & 1 deletion annotation-interface/pages/api/bricks/[id].ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NextApiHandler } from 'next';

import dbConnect from '../../../database/connect';
import dbConnect from '../../../database/helpers/connect';
import TextBrick from '../../../database/models/TextBrick';

const brickApi: NextApiHandler = async (req, res) => {
Expand Down
2 changes: 1 addition & 1 deletion annotation-interface/pages/api/bricks/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NextApiHandler } from 'next';

import dbConnect from '../../../database/connect';
import dbConnect from '../../../database/helpers/connect';
import TextBrick from '../../../database/models/TextBrick';

const brickApi: NextApiHandler = async (req, res) => {
Expand Down
2 changes: 1 addition & 1 deletion annotation-interface/pages/bricks/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
displayCategoryForIndex,
indexForDisplayCategory,
} from '../../contexts/brickFilter';
import dbConnect from '../../database/connect';
import dbConnect from '../../database/helpers/connect';
import TextBrick, { ITextBrick } from '../../database/models/TextBrick';

const EditBrick = ({
Expand Down
2 changes: 1 addition & 1 deletion annotation-interface/pages/bricks/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
useBrickFilterContext,
} from '../../contexts/brickFilter';
import { useLanguageContext } from '../../contexts/language';
import dbConnect from '../../database/connect';
import dbConnect from '../../database/helpers/connect';
import TextBrick from '../../database/models/TextBrick';

const AllTextBricks = ({
Expand Down

0 comments on commit 6a5e82a

Please sign in to comment.