-
Notifications
You must be signed in to change notification settings - Fork 1
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
Foundations for Warnings System #161
Changes from all commits
73f4cc2
63f5267
2e2f189
9ad76a0
3dc09b5
c591f6b
926a7bf
2a5a813
cb43cc4
6a76226
975489e
64e5c32
fc7d22d
cee8df2
bffc12d
30654b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
import _ from 'lodash'; | ||
import { AxiosInstance } from 'axios'; | ||
import ChtSession from './cht-session'; | ||
import { Config, ContactType } from '../config'; | ||
import { UserPayload } from '../services/user-payload'; | ||
import { AxiosInstance } from 'axios'; | ||
|
||
export type PlacePayload = { | ||
name: string; | ||
|
@@ -18,17 +18,6 @@ export type PlacePayload = { | |
[key: string]: any; | ||
}; | ||
|
||
export type RemotePlace = { | ||
id: string; | ||
name: string; | ||
lineage: string[]; | ||
ambiguities?: RemotePlace[]; | ||
|
||
// sadly, sometimes invalid or uncreated objects "pretend" to be remote | ||
// should reconsider this naming | ||
type: 'remote' | 'local' | 'invalid'; | ||
}; | ||
|
||
export class ChtApi { | ||
public readonly chtSession: ChtSession; | ||
private axiosInstance: AxiosInstance; | ||
|
@@ -174,26 +163,15 @@ export class ChtApi { | |
}; | ||
|
||
getPlacesWithType = async (placeType: string) | ||
: Promise<RemotePlace[]> => { | ||
const url = `medic/_design/medic-client/_view/contacts_by_type_freetext`; | ||
: Promise<any[]> => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this array of type There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not yet. Right now it returns the raw documents from CouchDB. I use |
||
const url = `medic/_design/medic-client/_view/contacts_by_type`; | ||
const params = { | ||
startkey: JSON.stringify([ placeType, 'name:']), | ||
endkey: JSON.stringify([ placeType, 'name:\ufff0']), | ||
key: JSON.stringify([placeType]), | ||
include_docs: true, | ||
}; | ||
console.log('axios.get', url, params); | ||
const resp = await this.axiosInstance.get(url, { params }); | ||
|
||
return resp.data.rows | ||
.map((row: any): RemotePlace => { | ||
const nameData = row.key[1]; | ||
return { | ||
id: row.id, | ||
name: nameData.substring('name:'.length), | ||
lineage: extractLineage(row.doc), | ||
type: 'remote', | ||
}; | ||
}); | ||
return resp.data.rows.map((row: any) => row.doc); | ||
}; | ||
|
||
getDoc = async (id: string): Promise<any> => { | ||
|
@@ -228,10 +206,3 @@ function minify(doc: any): any { | |
}; | ||
} | ||
|
||
function extractLineage(doc: any): string[] { | ||
if (doc?.parent?._id) { | ||
return [doc.parent._id, ...extractLineage(doc.parent)]; | ||
} | ||
|
||
return []; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { Config, ContactType } from '../config'; | ||
import SessionCache from '../services/session-cache'; | ||
import { stringify } from 'csv/sync'; | ||
|
||
type File = { | ||
filename: string; | ||
content: string; | ||
}; | ||
|
||
export default function getCredentialsFiles(sessionCache: SessionCache, contactTypes: ContactType[]): File[] { | ||
const files: File[] = []; | ||
for (const contactType of contactTypes) { | ||
const places = sessionCache.getPlaces({ type: contactType.name }); | ||
if (!places.length) { | ||
continue; | ||
} | ||
|
||
const rows = places.map((place) => [ | ||
...Object.values(place.hierarchyProperties).map(prop => prop.formatted), | ||
place.name, | ||
place.contact.properties.name?.formatted, | ||
place.contact.properties.phone?.formatted, | ||
place.userRoles.join(' '), | ||
place.creationDetails.username, | ||
place.creationDetails.password, | ||
]); | ||
|
||
const constraints = Config.getHierarchyWithReplacement(contactType); | ||
const props = Object.keys(places[0].hierarchyProperties) | ||
.map(prop => constraints.find(c => c.property_name === prop)!.friendly_name); | ||
const columns = [ | ||
...props, | ||
contactType.friendly, | ||
'name', | ||
'phone', | ||
'role', | ||
'username', | ||
'password', | ||
]; | ||
|
||
const content = stringify(rows, { | ||
columns, | ||
header: true, | ||
}); | ||
files.push({ | ||
filename: `${contactType.name}.csv`, | ||
content, | ||
}); | ||
} | ||
|
||
return files; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to the PR but nothing hints that
getPropertyWithName
might actually throw an error which i think makes it hard to reason about error handling in functions that call it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true. now that we assert it on startup, maybe we don't need it in the property? we know it is also there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah i think it would be clearer if
getPropertyWithName
returned a string or undefined; then the caller can choose to assert if undefined and throw if neededThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we assert at startup, we can guarantee it is never undefined at runtime
this allows us to safely make it a
string
which takes the burden off the calling codei personally like this since it leads to cleaner calling code. would you rather i not assert in the get and just use typescript operators to cast?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't we get a runtime error if the property name that was being accessed was not asserted at start up like
name
is? If this function is only used for gettingname
then maybe it can be renamed and args changed?