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

feat(frontend, backend): connect rxdb #6

Merged
merged 31 commits into from
Sep 14, 2022
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7ae8178
Make a terrible rxdb implementation
kand198 Aug 23, 2022
3c71f45
Fix issues with updating patients
kand198 Aug 30, 2022
f1aa58b
Style fixes
kand198 Aug 30, 2022
606a16c
Small fixes
kand198 Aug 31, 2022
a819b7f
Lay groundwork for GraphQL sync
kand198 Aug 31, 2022
0fa72d3
Add push replication
kand198 Sep 11, 2022
6319c7a
Fix bug with unknown consult entity
kand198 Sep 11, 2022
fbd61db
Change uid to id, connect RxDB pull
kand198 Sep 11, 2022
683b027
Fix issues with push-replication, DOB field
kand198 Sep 12, 2022
c66a117
Fix a few errors
kand198 Sep 12, 2022
10fef5a
Fix serialization issues
kand198 Sep 12, 2022
f6d261d
Never lose a patient again
kand198 Sep 12, 2022
02b2a88
Fix deletedAt
kand198 Sep 12, 2022
cc9eae9
Fix enums... again
kand198 Sep 12, 2022
65b73f4
!!Fix vulnerabilities (includes run of npm update)
kand198 Sep 12, 2022
7c94711
Fix npm CI(?)
kand198 Sep 12, 2022
084e0c2
roll back node version for CD
j-chad Sep 13, 2022
0013cdd
whoops wrong version
j-chad Sep 13, 2022
b976c4a
Fix frontend tests
kand198 Sep 14, 2022
1c93d38
Merge branch 'feat/connect-rxdb' of https://github.com/University-of-…
kand198 Sep 14, 2022
04ea031
Refactor for readability
kand198 Sep 14, 2022
7a6c1cf
Fix issues
kand198 Sep 14, 2022
89d8d85
Automatically select first tab where available
kand198 Sep 14, 2022
c56054b
Add required fields
kand198 Sep 14, 2022
6ae3ed0
Ugly hack to reduce traffic
kand198 Sep 14, 2022
cd8478b
match project file structure
kand198 Sep 14, 2022
651e006
fix nitpick
kand198 Sep 14, 2022
b18865e
match project file structure
kand198 Sep 14, 2022
c11d0ec
Fix error with patient ordering in feed
kand198 Sep 14, 2022
e924cae
move usePatients hook
kand198 Sep 14, 2022
739afec
Merge branch 'main' into feat/connect-rxdb
kand198 Sep 14, 2022
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
2 changes: 1 addition & 1 deletion .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 16.15.0
- uses: nrwl/nx-set-shas@v2
- run: npm ci

Expand Down
2 changes: 2 additions & 0 deletions apps/backend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import configuration, {
import { HealthModule } from '@supervision/health';
import { UsersModule } from '@supervision/users';
import { PatientsModule } from '@supervision/patients';
import { DateOfBirthScalar } from './patients/graphql/date-of-birth.scalar';

@Module({
imports: [
Expand All @@ -24,6 +25,7 @@ import { PatientsModule } from '@supervision/patients';
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: true,
resolvers: { DateOfBirth: DateOfBirthScalar },
}),
HealthModule,
UsersModule,
Expand Down
6 changes: 3 additions & 3 deletions apps/backend/src/app/patients/database/patient.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ export enum Gender {

@Entity({ name: 'patient' })
export class PatientEntity extends BaseEntity {
@Column('varchar', { length: 40 })
@Column('varchar', { length: 40, nullable: true })
kand198 marked this conversation as resolved.
Show resolved Hide resolved
firstName: string;

@Column('varchar', { length: 40 })
@Column('varchar', { length: 40, nullable: true })
lastName: string;

@Column('date')
@Column('date', { nullable: true })
dateOfBirth: Date;

@Column('enum', {
Expand Down
8 changes: 4 additions & 4 deletions apps/backend/src/app/patients/dto/create-patient.input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
@InputType()
export class CreatePatientInput {
// TODO: add field descriptions
@Field(() => String, { nullable: false })
@Field(() => String, { nullable: true })
firstName: string;

@Field(() => String, { nullable: false })
@Field(() => String, { nullable: true })
lastName: string;

@Field(() => Date, { nullable: false })
@Field(() => Date, { nullable: true })
dateOfBirth: Date;

@Field(() => Gender, { nullable: true })
Expand All @@ -25,7 +25,7 @@ export class CreatePatientInput {
@Field(() => String, { nullable: true })
school: string;

@Field(() => String, { nullable: true })
@Field(() => Number, { nullable: true })
yearLevel: number;

@Field(() => Date, { nullable: true })
Expand Down
15 changes: 15 additions & 0 deletions apps/backend/src/app/patients/dto/set-patient-input.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { InputType, Field, PartialType } from '@nestjs/graphql';
import { UpdatePatientInput } from './update-patient.input';

@InputType()
export class SetPatientInput extends PartialType(UpdatePatientInput) {
// TODO: add field descriptions
@Field(() => String, { nullable: false })
id: string;

@Field({ nullable: true })
deletedAt: Date;

@Field({ nullable: true })
updatedAt: Date;
}
21 changes: 21 additions & 0 deletions apps/backend/src/app/patients/graphql/date-of-birth.scalar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { GraphQLScalarType, Kind } from 'graphql';

export const DateOfBirthScalar = new GraphQLScalarType({
name: 'DateOfBirth',
description: 'Date custom scalar type',
parseValue(value: string | number | Date) {
return new Date(value); // value from the client
},
serialize(value: string | number | Date) {
if (value instanceof Date) {
return value.toISOString(); // value sent to the client
}
return new Date(value).toISOString();
},
parseLiteral(ast) {
if (ast.kind === Kind.INT) {
return new Date(ast.value); // ast value is always in string format
}
return null;
},
});
7 changes: 4 additions & 3 deletions apps/backend/src/app/patients/graphql/patient.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
import { BaseModel } from '@supervision/shared';
import { ConsultModel } from '@supervision/consults/graphql/consult.model';
import { Ethnicity, Gender } from '@supervision/patients';
import { DateOfBirthScalar } from './date-of-birth.scalar';

registerEnumType(Ethnicity, {
name: 'Ethnicity',
Expand All @@ -13,13 +14,13 @@ registerEnumType(Gender, {

@ObjectType({ description: 'patient' })
export class PatientModel extends BaseModel {
@Field({ nullable: false })
@Field({ nullable: true })
firstName: string;

@Field({ nullable: false })
@Field({ nullable: true })
lastName: string;

@Field({ nullable: false })
@Field(() => DateOfBirthScalar, { nullable: true })
dateOfBirth: Date;

@Field(() => Gender, { nullable: true })
Expand Down
13 changes: 13 additions & 0 deletions apps/backend/src/app/patients/graphql/patient.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { PatientService } from '@supervision/patients/patients.service';
import { CreatePatientInput } from '../dto/create-patient.input';
import { PatientEntity } from '../database';
import { UpdatePatientInput } from '../dto/update-patient.input';
import { SetPatientInput } from '../dto/set-patient-input';

@Resolver(() => PatientModel)
export class PatientResolver implements IReplicationResolver<PatientModel> {
Expand Down Expand Up @@ -38,6 +39,18 @@ export class PatientResolver implements IReplicationResolver<PatientModel> {
);
}

@Mutation(() => PatientModel, { nullable: true })
async setPatients(
@Args({
name: 'setPatientsInput',
type: () => [SetPatientInput],
nullable: true,
})
setPatientsInput: SetPatientInput[]
): Promise<PatientModel | null> {
return await this.patientService.set(setPatientsInput);
}

@Query(() => PatientModel)
async patient(@Args('id') id: string): Promise<PatientModel> {
return await this.patientService.findOne(id);
Expand Down
6 changes: 5 additions & 1 deletion apps/backend/src/app/patients/patients.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { PatientEntity } from '@supervision/patients/database';
import { PatientResolver } from '@supervision/patients/graphql';
import { PatientService } from '@supervision/patients/patients.service';
import { ConsultEntity } from '@supervision/consults';

@Module({
imports: [TypeOrmModule.forFeature([PatientEntity])],
imports: [
TypeOrmModule.forFeature([PatientEntity]),
TypeOrmModule.forFeature([ConsultEntity]),
],
exports: [TypeOrmModule],
providers: [PatientService, PatientResolver],
})
Expand Down
6 changes: 6 additions & 0 deletions apps/backend/src/app/patients/patients.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm';
import { PatientEntity } from '@supervision/patients';
import { Repository, SelectQueryBuilder } from 'typeorm';
import { CreatePatientInput } from './dto/create-patient.input';
import { SetPatientInput } from './dto/set-patient-input';
import { UpdatePatientInput } from './dto/update-patient.input';

@Injectable()
Expand Down Expand Up @@ -31,6 +32,11 @@ export class PatientService {
return await this.patientsRepository.save(patient);
}

async set(patients: SetPatientInput[]): Promise<PatientEntity> {
const newPatients = await this.patientsRepository.save(patients);
return newPatients[newPatients.length - 1];
}

async findOne(id: string): Promise<PatientEntity> {
return await this.patientsRepository.findOneBy({ id: id });
}
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/app/shared/database/base.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export abstract class BaseEntity {
@CreateDateColumn({ type: 'timestamptz' })
createdAt: Date;

@DeleteDateColumn({ type: 'timestamptz' })
@DeleteDateColumn({ type: 'timestamptz', nullable: true })
deletedAt: Date;

@UpdateDateColumn({ type: 'timestamptz' })
Expand Down
7 changes: 6 additions & 1 deletion apps/backend/src/app/users/users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ export class UserService {
limit: number
): Promise<UserEntity[]> {
let query: SelectQueryBuilder<UserEntity>;
if (minUpdatedAt === undefined || lastId === undefined) {
if (
minUpdatedAt === undefined ||
lastId === undefined ||
minUpdatedAt?.getTime() === 0 ||
lastId === ''
) {
query = this.usersRepository.createQueryBuilder('user');
} else {
query = this.usersRepository
Expand Down
1 change: 1 addition & 0 deletions apps/frontend/src/app/hooks/usePatients/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './usePatients';
40 changes: 40 additions & 0 deletions apps/frontend/src/app/hooks/usePatients/usePatients.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { IPatient } from '@patients';
kand198 marked this conversation as resolved.
Show resolved Hide resolved
import { uuid } from 'uuidv4';
import { useState, useEffect, useCallback } from 'react';
import { RxDatabase } from 'rxdb';
import { patientDatabase } from 'database';

export const usePatients = () => {
const [patientsDb, setPatientsDb] = useState<RxDatabase>();
const [patients, setPatients] = useState<IPatient[]>([]);

const newPatient = useCallback(() => {
const newPatient = {
id: uuid(),
};
patientsDb?.['patients'].insert(newPatient);
return newPatient.id;
}, [patientsDb]);

const updatePatient = (patient: IPatient) =>
patientsDb?.['patients'].atomicUpsert(patient);

useEffect(() => {
if (!patientsDb) {
patientDatabase
.get()
?.then((db: RxDatabase | null) => {
db && setPatientsDb(db);
db && db['patients'].find().$.subscribe(setPatients);
return () => db?.['patients'].find().$.unsubscribe();
})
.catch((error: Error) => {
console.error(error);
});
}
}, [patientsDb]);

return { patients, newPatient, updatePatient };
};

export default usePatients;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type EthnicitySelectProps = {
onChange: (value: string | null) => void;
};

enum Ethnicities {
export enum Ethnicities {
'NZ European' = 'nz european',
'Other European' = 'other european',
'NZ Maori' = 'nz maori',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type GenderSelectProps = {
onChange: (value: string | null) => void;
};

enum Gender {
export enum Gender {
'Female' = 'female',
'Male' = 'male',
'Other' = 'other',
Expand Down
Loading