diff --git a/admin/src/js/services/contact-types.js b/admin/src/js/services/contact-types.js index 068a5c24396..a5e04dcce25 100644 --- a/admin/src/js/services/contact-types.js +++ b/admin/src/js/services/contact-types.js @@ -1,4 +1,5 @@ const contactTypesUtils = require('@medic/contact-types-utils'); +const { DOC_TYPES } = require('@medic/constants'); angular.module('inboxServices').service('ContactTypes', function( Settings @@ -34,7 +35,7 @@ angular.module('inboxServices').service('ContactTypes', function( if (!type) { return false; } - return type === 'contact' || // configurable hierarchy + return type === DOC_TYPES.CONTACT || // configurable hierarchy contactTypesUtils.isHardcodedType(type); // hardcoded }, diff --git a/apply-fix.js b/apply-fix.js new file mode 100644 index 00000000000..b6dc227a491 --- /dev/null +++ b/apply-fix.js @@ -0,0 +1,73 @@ +const fs = require('fs'); + +const edits = [ + { + file: 'webapp/src/ts/modules/tasks/tasks-content.component.ts', + imports: [{ after: null, add: "import { DOC_TYPES } from '@medic/constants';\n" }], + replacements: [["action.type === 'contact'", "action.type === DOC_TYPES.CONTACT"]], + }, + { + file: 'webapp/src/ts/modules/messages/messages-content.component.ts', + imports: [{ after: null, add: "import { DOC_TYPES } from '@medic/constants';\n" }], + replacements: [["if (type === 'contact')", "if (type === DOC_TYPES.CONTACT)"]], + }, + { + file: 'webapp/src/ts/services/contact-types.service.ts', + imports: [{ after: null, add: "import { DOC_TYPES } from '@medic/constants';\n" }], + replacements: [["type === 'contact' || // configurable hierarchy", "type === DOC_TYPES.CONTACT || // configurable hierarchy"]], + }, + { + file: 'webapp/src/ts/reducers/contacts.ts', + imports: [{ after: null, add: "import { DOC_TYPES } from '@medic/constants';\n" }], + replacements: [["contact.type === 'contact'", "contact.type === DOC_TYPES.CONTACT"]], + }, + { + file: 'webapp/src/js/bootstrapper/offline-ddocs/medic-offline-freetext/contacts_by_type_freetext.js', + imports: [{ after: null, add: "const { DOC_TYPES } = require('@medic/constants');\n" }], + replacements: [ + ["doc.type !== 'contact'", "doc.type !== DOC_TYPES.CONTACT"], + ["typeIndex === -1 && doc.type === 'contact'", "typeIndex === -1 && doc.type === DOC_TYPES.CONTACT"], + ], + }, + { + file: 'webapp/src/ts/modules/contacts/contacts-edit.component.ts', + imports: [{ after: null, add: "import { DOC_TYPES } from '@medic/constants';\n" }], + replacements: [["type: 'contact',", "type: DOC_TYPES.CONTACT,"]], + }, + { + file: 'webapp/src/ts/services/form.service.ts', + imports: [{ after: null, add: "import { DOC_TYPES } from '@medic/constants';\n" }], + replacements: [ + [": { type: 'contact', contact_type: type };", ": { type: DOC_TYPES.CONTACT, contact_type: type };"], + ["this.type !== 'contact' && this.type !== 'training-card';", "this.type !== DOC_TYPES.CONTACT && this.type !== 'training-card';"], + ], + }, + { + file: 'webapp/src/ts/services/get-data-records.service.ts', + imports: [{ after: null, add: "import { DOC_TYPES } from '@medic/constants';\n" }], + replacements: [["this.getRecords(ids, 'contact', options);", "this.getRecords(ids, DOC_TYPES.CONTACT, options);"]], + }, +]; + +for (const edit of edits) { + let content = fs.readFileSync(edit.file, 'utf8'); + + for (const rep of edit.replacements) { + if (!content.includes(rep[0])) { + console.error(`WARNING: pattern not found in ${edit.file}:\n ${rep[0]}`); + continue; + } + content = content.replace(rep[0], rep[1]); + } + + // add import at the very top if not already present + const importLine = edit.imports[0].add; + if (!content.includes("from '@medic/constants'") && !content.includes("require('@medic/constants')")) { + content = importLine + content; + } + + fs.writeFileSync(edit.file, content, 'utf8'); + console.log(`Updated: ${edit.file}`); +} + +console.log('\nDone. Run `git diff` to review.'); \ No newline at end of file diff --git a/shared-libs/cht-datasource/src/local/person.ts b/shared-libs/cht-datasource/src/local/person.ts index e3cf96c3e75..912923c242d 100644 --- a/shared-libs/cht-datasource/src/local/person.ts +++ b/shared-libs/cht-datasource/src/local/person.ts @@ -1,5 +1,6 @@ import { Doc, isDoc } from '../libs/doc'; import contactTypeUtils from '@medic/contact-types-utils'; +import { DOC_TYPES } from '@medic/constants'; import { assertHasRequiredField, DataObject, Nullable, Page } from '../libs/core'; import * as Qualifier from '../qualifier'; import { ContactTypeQualifier, UuidQualifier } from '../qualifier'; @@ -29,7 +30,7 @@ const getTypeProperties = (settings: DataObject, input: Input.v1.PersonInput) => throw new InvalidArgumentError(`[${input.type}] is not a valid person type.`); } return customType - ? { contact_type: input.type, type: 'contact' } + ? { contact_type: input.type, type: DOC_TYPES.CONTACT } : { type: input.type }; }; diff --git a/shared-libs/cht-datasource/src/local/place.ts b/shared-libs/cht-datasource/src/local/place.ts index 1bc3fa5eec3..7f47d8855a2 100644 --- a/shared-libs/cht-datasource/src/local/place.ts +++ b/shared-libs/cht-datasource/src/local/place.ts @@ -19,7 +19,7 @@ import { } from './libs/lineage'; import { assertPlaceInput } from '../libs/parameter-validators'; import * as LocalContact from './contact'; -import { CONTACT_TYPES } from '@medic/constants'; +import { CONTACT_TYPES, DOC_TYPES } from '@medic/constants'; const DEFAULT_PLACE_TYPES_DICT: Record = { [CONTACT_TYPES.DISTRICT_HOSPITAL]: { id: CONTACT_TYPES.DISTRICT_HOSPITAL }, @@ -49,7 +49,7 @@ const getTypeProperties = (settings: DataObject, input: Input.v1.PlaceInput) => getPlaceType(settings, input); const customType = contactTypeUtils.getTypeById(settings, input.type); return customType - ? { contact_type: input.type, type: 'contact' } +? { contact_type: input.type, type: DOC_TYPES.CONTACT } : { type: input.type }; }; diff --git a/shared-libs/constants/src/index.js b/shared-libs/constants/src/index.js index ae4309d9984..3f3e2b3fbc9 100644 --- a/shared-libs/constants/src/index.js +++ b/shared-libs/constants/src/index.js @@ -26,7 +26,8 @@ const DOC_TYPES = { TOKEN_LOGIN: 'token_login', TRANSLATIONS: 'translations', DATA_RECORD: 'data_record', - UI_EXTENSION: 'ui-extension' + UI_EXTENSION: 'ui-extension', + CONTACT: 'contact', }; // HTTP Headers diff --git a/shared-libs/contact-types-utils/src/index.js b/shared-libs/contact-types-utils/src/index.js index cb206192f36..3fe858d533b 100644 --- a/shared-libs/contact-types-utils/src/index.js +++ b/shared-libs/contact-types-utils/src/index.js @@ -1,4 +1,4 @@ -const { CONTACT_TYPES } = require('@medic/constants'); +const { CONTACT_TYPES, DOC_TYPES } = require('@medic/constants'); const HARDCODED_PERSON_TYPE = 'person'; const HARDCODED_TYPES = [ @@ -21,7 +21,7 @@ const getTypeId = (doc) => { if (!doc) { return; } - return doc.type === 'contact' ? doc.contact_type : doc.type; +return doc.type === DOC_TYPES.CONTACT ? doc.contact_type : doc.type; }; const getTypeById = (config, typeId) => { diff --git a/shared-libs/lineage/src/utils.js b/shared-libs/lineage/src/utils.js index 7b074eaaec7..b7328562cec 100644 --- a/shared-libs/lineage/src/utils.js +++ b/shared-libs/lineage/src/utils.js @@ -6,10 +6,8 @@ const isContact = doc => { if (!doc) { return; } - - return doc.type === 'contact' || contactTypeUtils.HARDCODED_TYPES.includes(doc.type); + return doc.type === DOC_TYPES.CONTACT || contactTypeUtils.HARDCODED_TYPES.includes(doc.type); }; - const getId = (item) => item && (typeof item === 'string' ? item : item._id); // don't process linked docs for non-contact types diff --git a/shared-libs/summaries/src/index.js b/shared-libs/summaries/src/index.js index d84a34e26f9..e87d0fbc659 100644 --- a/shared-libs/summaries/src/index.js +++ b/shared-libs/summaries/src/index.js @@ -56,7 +56,7 @@ const isContact = (doc) => { if (!type) { return false; } - return type === 'contact' || contactTypesUtils.isHardcodedType(type); + return type === DOC_TYPES.CONTACT || contactTypesUtils.isHardcodedType(type); }; const isReport = (doc) => { diff --git a/webapp/src/js/bootstrapper/offline-ddocs/medic-offline-freetext/contacts_by_type_freetext.js b/webapp/src/js/bootstrapper/offline-ddocs/medic-offline-freetext/contacts_by_type_freetext.js index 689a5669701..4ac5c6dd4f4 100644 --- a/webapp/src/js/bootstrapper/offline-ddocs/medic-offline-freetext/contacts_by_type_freetext.js +++ b/webapp/src/js/bootstrapper/offline-ddocs/medic-offline-freetext/contacts_by_type_freetext.js @@ -1,3 +1,4 @@ +const { DOC_TYPES } = require('@medic/constants'); module.exports.map = (doc) => { const skip = [ '_id', '_rev', 'type', 'refid', 'geolocation' ]; const keyShouldBeSkipped = key => skip.indexOf(key) !== -1 || /_date$/.test(key); @@ -32,7 +33,7 @@ module.exports.map = (doc) => { }; const getType = () => { - if (doc.type !== 'contact') { + if (doc.type !== DOC_TYPES.CONTACT) { return doc.type; } @@ -42,7 +43,7 @@ module.exports.map = (doc) => { const getTypeIndex = type => { const types = [ 'district_hospital', 'health_center', 'clinic', 'person' ]; const typeIndex = types.indexOf(type); - if (typeIndex === -1 && doc.type === 'contact') { + if (typeIndex === -1 && doc.type === DOC_TYPES.CONTACT) { return type; } diff --git a/webapp/src/ts/modules/contacts/contacts-edit.component.ts b/webapp/src/ts/modules/contacts/contacts-edit.component.ts index 13105654cd8..1aec99e3503 100644 --- a/webapp/src/ts/modules/contacts/contacts-edit.component.ts +++ b/webapp/src/ts/modules/contacts/contacts-edit.component.ts @@ -1,3 +1,4 @@ +import { DOC_TYPES } from '@medic/constants'; import { AfterViewInit, Component, NgZone, OnDestroy, OnInit } from '@angular/core'; import { combineLatest, Subscription } from 'rxjs'; import { Store } from '@ngrx/store'; @@ -252,7 +253,7 @@ export class ContactsEditComponent implements OnInit, OnDestroy, AfterViewInit { } else { // adding this.trackMetadata.action = 'add'; this.contact = { - type: 'contact', + type: DOC_TYPES.CONTACT, contact_type: this.routeSnapshot.params?.type, parent: this.routeSnapshot.params?.parent_id || '', }; diff --git a/webapp/src/ts/modules/messages/messages-content.component.ts b/webapp/src/ts/modules/messages/messages-content.component.ts index 0f2f49c3228..9cedef12fb1 100644 --- a/webapp/src/ts/modules/messages/messages-content.component.ts +++ b/webapp/src/ts/modules/messages/messages-content.component.ts @@ -1,3 +1,4 @@ +import { DOC_TYPES } from '@medic/constants'; import { AfterViewChecked, AfterViewInit, @@ -178,7 +179,7 @@ export class MessagesContentComponent implements OnInit, OnDestroy, AfterViewIni // See URL parameter "id" note at top of file private getContactable(id, type) { - if (type === 'contact') { + if (type === DOC_TYPES.CONTACT) { return this.lineageModelGeneratorService .contact(id) .catch(err => { diff --git a/webapp/src/ts/modules/tasks/tasks-content.component.ts b/webapp/src/ts/modules/tasks/tasks-content.component.ts index eab48e6f896..b65e0eb1cb6 100644 --- a/webapp/src/ts/modules/tasks/tasks-content.component.ts +++ b/webapp/src/ts/modules/tasks/tasks-content.component.ts @@ -1,3 +1,4 @@ +import { DOC_TYPES } from '@medic/constants'; import { Component, OnDestroy, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { combineLatest, Subject, Subscription } from 'rxjs'; @@ -307,7 +308,7 @@ export class TasksContentComponent implements OnInit, OnDestroy { .then(() => this.preloadTaskGroupContact(action)); } - if (action.type === 'contact') { + if (action.type === DOC_TYPES.CONTACT) { if (action.content?.parent_id && action.content?.type) { this.router.navigate(['/contacts', action.content.parent_id, 'add', action.content.type || '']); } else if (action.content?.type) { diff --git a/webapp/src/ts/reducers/contacts.ts b/webapp/src/ts/reducers/contacts.ts index 4b4d867e127..8d531e1254e 100644 --- a/webapp/src/ts/reducers/contacts.ts +++ b/webapp/src/ts/reducers/contacts.ts @@ -1,3 +1,4 @@ +import { DOC_TYPES } from '@medic/constants'; import { createReducer, on } from '@ngrx/store'; import { UniqueSortedList } from '@mm-reducers/utils'; @@ -16,7 +17,7 @@ const initialState = { }; const getContactTypeOrder = (contact) => { - if (contact.type === 'contact') { + if (contact.type === DOC_TYPES.CONTACT) { const idx = ContactTypesService.HARDCODED_TYPES().indexOf(contact.contact_type); if (idx !== -1) { // matches a hardcoded type - order by the index diff --git a/webapp/src/ts/services/contact-types.service.ts b/webapp/src/ts/services/contact-types.service.ts index 137747d986b..ee5c06dd9cf 100644 --- a/webapp/src/ts/services/contact-types.service.ts +++ b/webapp/src/ts/services/contact-types.service.ts @@ -1,3 +1,4 @@ +import { DOC_TYPES } from '@medic/constants'; import { Injectable } from '@angular/core'; import * as contactTypesUtils from '@medic/contact-types-utils'; @@ -48,7 +49,7 @@ export class ContactTypesService { if (!type) { return false; } - return type === 'contact' || // configurable hierarchy + return type === DOC_TYPES.CONTACT || // configurable hierarchy contactTypesUtils.isHardcodedType(type); // hardcoded } diff --git a/webapp/src/ts/services/form.service.ts b/webapp/src/ts/services/form.service.ts index f07f0040fd4..5adc4f7a570 100644 --- a/webapp/src/ts/services/form.service.ts +++ b/webapp/src/ts/services/form.service.ts @@ -1,3 +1,4 @@ +import { DOC_TYPES } from '@medic/constants'; import { Injectable, NgZone } from '@angular/core'; import { Store } from '@ngrx/store'; import { toBik_text } from 'bikram-sambat'; @@ -400,7 +401,7 @@ export class FormService { const { form, xmlVersion, duplicateCheck } = formInfo; const typeFields = this.contactTypesService.isHardcodedType(type) ? { type } - : { type: 'contact', contact_type: type }; + : { type: DOC_TYPES.CONTACT, contact_type: type }; const docs = await this.contactSaveService.save(form, docId, typeFields, xmlVersion); const preparedDocs = await this.applyTransitions(docs); @@ -477,6 +478,6 @@ export class WebappEnketoFormContext implements EnketoFormContext { requiresContact() { // Users can access contact forms even when they don't have a contact associated. - return this.type !== 'contact' && this.type !== 'training-card'; + return this.type !== DOC_TYPES.CONTACT && this.type !== 'training-card'; } } diff --git a/webapp/src/ts/services/get-data-records.service.ts b/webapp/src/ts/services/get-data-records.service.ts index a3b5dccf3fb..b38e3c3f838 100644 --- a/webapp/src/ts/services/get-data-records.service.ts +++ b/webapp/src/ts/services/get-data-records.service.ts @@ -1,3 +1,4 @@ +import { DOC_TYPES } from '@medic/constants'; import { Injectable } from '@angular/core'; import { DbService } from '@mm-services/db.service'; @@ -47,7 +48,7 @@ export class GetDataRecordsService { } getContacts(ids: string[], options: { hydrateContactNames?: boolean, include_docs?: boolean } = {}) { - return this.getRecords(ids, 'contact', options); + return this.getRecords(ids, DOC_TYPES.CONTACT, options); } getReports(ids: string[], options: { hydrateContactNames?: boolean, include_docs?: boolean } = {}) { diff --git a/webapp/web-components/cht-form/src/app.component.ts b/webapp/web-components/cht-form/src/app.component.ts index 20315879169..e7440788492 100644 --- a/webapp/web-components/cht-form/src/app.component.ts +++ b/webapp/web-components/cht-form/src/app.component.ts @@ -9,7 +9,7 @@ import { NgIf, DOCUMENT } from '@angular/common'; import { TranslatePipe } from '@ngx-translate/core'; import { CHTDatasourceService } from '@mm-services/cht-datasource.service'; import { CHTDatasourceService as CHTDatasourceServiceStub } from './stubs/cht-datasource.service'; -import { CONTACT_TYPES } from '@medic/constants'; +import { CONTACT_TYPES, DOC_TYPES } from '@medic/constants'; const DEFAULT_FORM_ID = 'cht-form-id'; @@ -157,7 +157,7 @@ export class AppComponent { if (contactType) { const typeFields = this.HARDCODED_TYPES.includes(contactType) ? { type: contactType } - : { type: 'contact', contact_type: contactType }; + : { type: DOC_TYPES.CONTACT, contact_type: contactType }; const { preparedDocs } = await this.contactSaveService.save(currentForm, null, typeFields, null); return preparedDocs; } @@ -305,6 +305,6 @@ class ChtFormEnketoFormContext implements EnketoFormContext { } get type() { - return this.contactType ? 'contact': 'report'; - } + return this.contactType ? DOC_TYPES.CONTACT : 'report'; + } }