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

Work on db issues and dev docs #2002

Closed
wants to merge 6 commits into from
Closed
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
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, OnInit, Input, AfterContentInit } from '@angular/core';
import { Component, OnInit, Input, AfterContentInit, ChangeDetectorRef } from '@angular/core';
import { CaseEvent } from '../../classes/case-event.class';
import { Case } from '../../classes/case.class';
import { CaseEventDefinition } from '../../classes/case-event-definition.class';
Expand Down Expand Up @@ -30,7 +30,9 @@ export class CaseEventListItemComponent implements AfterContentInit {
renderedTemplateListItemPrimary = ''
renderedTemplateListItemSecondary = ''

constructor() { }
constructor(private ref: ChangeDetectorRef) {
ref.detach()
}

ngAfterContentInit() {
const getVariable = (variableName) => {
Expand All @@ -50,6 +52,7 @@ export class CaseEventListItemComponent implements AfterContentInit {
eval(`this.renderedTemplateListItemIcon = this.caseDefinition.templateCaseEventListItemIcon ? \`${this.caseDefinition.templateCaseEventListItemIcon}\` : \`${this.defaultTemplateListItemIcon}\``)
eval(`this.renderedTemplateListItemPrimary = this.caseDefinition.templateCaseEventListItemPrimary ? \`${this.caseDefinition.templateCaseEventListItemPrimary}\` : \`${this.defaultTemplateListItemPrimary}\``)
eval(`this.renderedTemplateListItemSecondary = this.caseDefinition.templateCaseEventListItemSecondary ? \`${this.caseDefinition.templateCaseEventListItemSecondary}\` : \`${this.defaultTemplateListItemSecondary}\``)
this.ref.detectChanges()
}

}
6 changes: 3 additions & 3 deletions client/src/app/case/components/case/case.component.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<app-case-breadcrumb *ngIf="ready" [caseId]="caseService.case._id"></app-case-breadcrumb>
<app-case-breadcrumb [caseId]="caseService.case._id"></app-case-breadcrumb>

<div *ngIf="ready" class="subject-header">
<div class="subject-header">
<h1>
<span [innerHTML]="templateTitle|unsanitizeHtml"></span>
</h1>
Expand All @@ -12,7 +12,7 @@ <h1>
</div>
</div>

<div *ngIf="ready" class="wrapper">
<div class="wrapper">
<div class="cover-when-not-confirmed" *ngIf="caseService.openCaseConfirmed === false"></div>
<div *ngFor="let eventInfo of caseEventsInfo">
<app-case-event-list-item *ngFor="let caseEvent of eventInfo.caseEvents" [caseEvent]="caseEvent"
Expand Down
25 changes: 14 additions & 11 deletions client/src/app/case/components/case/case.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, AfterContentInit } from '@angular/core';
import { Component, AfterContentInit, ChangeDetectorRef } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { CaseService } from '../../services/case.service'
import { CaseEventDefinition } from '../../classes/case-event-definition.class';
Expand Down Expand Up @@ -28,21 +28,22 @@ export class CaseComponent implements AfterContentInit {

constructor(
private route: ActivatedRoute,
private caseService: CaseService
private caseService: CaseService,
private ref: ChangeDetectorRef
) {
ref.detach()
this.window = window
}

async ngAfterContentInit() {
this.route.params.subscribe(async params => {
if (!this.caseService.case || params.id !== this.caseService.case._id) {
await this.caseService.load(params.id)
this.caseService.openCaseConfirmed = false
}
this.window.caseService = this.caseService
this.calculateTemplateData()
this.ready = true
})
const caseId = window.location.hash.split('/')[2]
if (!this.caseService.case || caseId !== this.caseService.case._id) {
await this.caseService.load(caseId)
this.caseService.openCaseConfirmed = false
}
this.window.caseService = this.caseService
this.calculateTemplateData()
this.ready = true
}

calculateTemplateData() {
Expand Down Expand Up @@ -75,10 +76,12 @@ export class CaseComponent implements AfterContentInit {
})
this.selectedNewEventType = ''
this.inputSelectedDate = moment(new Date()).format('YYYY-MM-DD')
this.ref.detectChanges()
}

onOpenCaseConfirmButtonClick() {
this.caseService.openCaseConfirmed = true
this.ref.detectChanges()
}

async onSubmit() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, ChangeDetectorRef } from '@angular/core';
import { CaseEvent } from '../../classes/case-event.class';
import { Case } from '../../classes/case.class';
import { CaseEventDefinition } from '../../classes/case-event-definition.class';
Expand Down Expand Up @@ -37,18 +37,25 @@ export class EventFormListItemComponent implements OnInit {
renderedTemplateListItemPrimary = ''
renderedTemplateListItemSecondary = ''

constructor(private formService:TangyFormService) { }
constructor(
private formService:TangyFormService,
private ref: ChangeDetectorRef
) {
ref.detach()
}

async ngOnInit() {
const response = await this.formService.getResponse(this.eventForm.formResponseId)
const getValue = (variableName) => {
const variablesByName = response.items.reduce((variablesByName,item) => {
for (let input of item.inputs) {
variablesByName[input.name] = input.value
}
return variablesByName
}, {})
return !Array.isArray(variablesByName[variableName]) ? variablesByName[variableName] : variablesByName[variableName].reduce((optionThatIsOn, option) => optionThatIsOn = option.value === 'on' ? option.name : optionThatIsOn, '')
if (response) {
const variablesByName = response.items.reduce((variablesByName,item) => {
for (let input of item.inputs) {
variablesByName[input.name] = input.value
}
return variablesByName
}, {})
return !Array.isArray(variablesByName[variableName]) ? variablesByName[variableName] : variablesByName[variableName].reduce((optionThatIsOn, option) => optionThatIsOn = option.value === 'on' ? option.name : optionThatIsOn, '')
}
}
const getCaseVariable = (variableName) => {
const variablesByName = this.case.items.reduce((variablesByName,item) => {
Expand All @@ -70,6 +77,7 @@ export class EventFormListItemComponent implements OnInit {
eval(`this.renderedTemplateListItemIcon = this.caseDefinition.templateEventFormListItemIcon ? \`${this.caseDefinition.templateEventFormListItemIcon}\` : \`${this.defaultTemplateListItemIcon}\``)
eval(`this.renderedTemplateListItemPrimary = this.caseDefinition.templateEventFormListItemPrimary ? \`${this.caseDefinition.templateEventFormListItemPrimary}\` : \`${this.defaultTemplateListItemPrimary}\``)
eval(`this.renderedTemplateListItemSecondary = this.caseDefinition.templateEventFormListItemSecondary ? \`${this.caseDefinition.templateEventFormListItemSecondary}\` : \`${this.defaultTemplateListItemSecondary}\``)
this.ref.detectChanges()
}

}
5 changes: 3 additions & 2 deletions client/src/app/shared/_services/search.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ class MockUserService {
class MockAppConfigService {
getAppConfig() {
return {
sharedUserDatabase: false
}
sharedUserDatabase: false
}
}
}

Expand All @@ -57,6 +57,7 @@ class MockFormsInfoService {
description: 'test test',
type: 'form',
listed: true,
archived: false,
title: 'Example',
searchSettings: <FormSearchSettings>{
shouldIndex: true,
Expand Down
4 changes: 2 additions & 2 deletions docs/developer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
- [modules.md](modules.md)

## Form Display
- [viewing-forms-and-data.md](Viewing Forms and Form Data)
- [supporting-custom-elements.md](Supporting custom elements)
- [Viewing Forms and Form Data](viewing-forms-and-data.md)
- [Supporting custom elements](supporting-custom-elements.md)

## Debugging
- [debugging-reporting.md](debugging-reporting.md)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/developer/assets/template-debugger.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 76 additions & 1 deletion docs/developer/viewing-forms-and-data.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,83 @@
# Viewing Forms and Form Data

Use TangyFormService to retrieve form definitions and response data:
## TangyFormService

On a broad level, you could use TangyFormService to retrieve form definitions and response data:

```js
this.formResponse = await this.tangyFormService.getResponse(this.eventForm.formResponseId)
const tangyFormMarkup = await this.tangyFormService.getFormMarkup(this.eventFormDefinition.formId)
```

But there are other ways of getting data out of Tangerine. First you need to see where you are getting data from.

## Mapping of components to forms

EventFormListItemComponent - listing of forms in an event
CaseEventListItemComponent - listing of events (such as Followup ANC Visits) in a case.

## Helper functions already in components

In the component for a list, helper functions may already expose the properties you need to populate a template. In EventFormListItemComponent, notice the variable exposed:

```js
const response = await this.formService.getResponse(this.eventForm.formResponseId)
const getValue = (variableName) => {
// more code inside getValue();
}, {})
// snip
const caseInstance = this.case
const caseDefinition = this.caseDefinition
const caseEventDefinition = this.caseEventDefinition
const caseEvent = this.caseEvent
const eventForm = this.eventForm
const eventFormDefinition = this.eventFormDefinition
const formatDate = (unixTimeInMilliseconds, format) => moment(new Date(unixTimeInMilliseconds)).format(format)
const TRANSLATE = _TRANSLATE
eval(`this.renderedTemplateListItemIcon = this.caseDefinition.templateEventFormListItemIcon ? \`${this.caseDefinition.templateEventFormListItemIcon}\` : \`${this.defaultTemplateListItemIcon}\``)
eval(`this.renderedTemplateListItemPrimary = this.caseDefinition.templateEventFormListItemPrimary ? \`${this.caseDefinition.templateEventFormListItemPrimary}\` : \`${this.defaultTemplateListItemPrimary}\``)
eval(`this.renderedTemplateListItemSecondary = this.caseDefinition.templateEventFormListItemSecondary ? \`${this.caseDefinition. v}\` : \`${this.defaultTemplateListItemSecondary}\``)
```
If there is not a response for a form, response will be false; therefore, if you do a getValue() in your template, be sure to test if response is true.

If you wish to display the startDatetime in your template, note that is is part of the response object - it is returned as response.startDatetime. In other cases - for values inside the form - use getValue(variableName) - but test if response is true first! Also, remember that the variableName is one of the id's in the inputs array, which is inside each item in the items array.

## Testing your templates

Here's an easy way to test your template code: in the js console, use the copy() function to copy the value for your template:

```js
copy(this.caseDefinition.templateEventFormListItemSecondary)
```
Then add the fields or functions you need. In this case, I'm adding a getValue:

```js
`<t-lang en>Status</t-lang><t-lang fr>Statut</t-lang>: ${!eventForm.complete ? '<t-lang en>Incomplete</t-lang><t-lang fr>Incomplète</t-lang>' : '<t-lang en>Complete</t-lang><t-lang fr>Achevée</t-lang>'} ${response ? `Version: ${getValue("content_release_version")}`: ''}`
```

Output:
```js
"<t-lang en>Status</t-lang><t-lang fr>Statut</t-lang>: <t-lang en>Complete</t-lang><t-lang fr>Achevée</t-lang> Start date: 3/13/2020, 11:25:19 AM"
```

Note that I was testing for existence of response, and also nesting templates to show the "Version" text if there was a value for content_release_version.

Another example:

`<t-lang en>Status</t-lang><t-lang fr>Statut</t-lang>: ${!eventForm.complete ? '<t-lang en>Incomplete</t-lang><t-lang fr>Incomplète</t-lang>' : '<t-lang en>Complete</t-lang><t-lang fr>Achevée</t-lang>'} ${response ? `Start date: ${response.startDatetime}`: ''}`

## debugging templates

To make the dev tool stop on a breakpoint in a Case Definition's template, add the following debugger statement to the content of the template.

```js
${(()=>{debugger})()}
```

![alt text](assets/template-debugger.png "Template debugger")

When that template loads, the Chrome devtools will pause and you can inspect local variables/functions available and try running them in the console. Note that different templates will have different helper functions and variables available.

![alt text](assets/inspect-helper-functions.png "Inspect Helper Functions")