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

Allow user to select from multiple location lists in tangy-location-widget #367

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
12 changes: 12 additions & 0 deletions demo/assets/location-list-metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"id": "default-location-list",
"name": "Default Location List",
"path": "./assets/location-list.json"
},
{
"id": "hospitals",
"name": "Hospitals",
"path": "./assets/locations/hospitals.json"
}
]
43 changes: 43 additions & 0 deletions demo/assets/locations/hospitals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"locationsLevels": ["ward", "clinic"],
"locations": {
"ward1": {
"id": "ward1",
"label": "ward 1",
"children": {
"clinic1": {
"id": "clinic1",
"label": "clinic 1",
"latitude": 44.46567,
"longitude": -73.21911
},
"clinic2": {
"id": "clinic2",
"label": "clinic 2",
"latitude": 44.45308,
"longitude": -73.19576
}
}
},
"ward2": {
"id": "ward2",
"label": "ward 2",
"children": {
"clinic3": {
"id": "clinic3",
"label": "clinic 3",
"latitude": 44.46567,
"longitude": -73.21911

},
"clinic4": {
"id": "clinic4",
"label": "clinic 4",
"latitude": 44.46567,
"longitude": -73.21911

}
}
}
}
}
8 changes: 6 additions & 2 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@

<script type="module" src="../tangy-form-editor.js"></script>


<custom-style>
<style is="custom-style" include="demo-pages-shared-styles">
</style>
</custom-style>
</head>
<body>
<tangy-form-editor files-endpoint="./files.json">
<tangy-form-editor
files-endpoint="./files.json"
location-list-metadata='[{"id":"default-location-list","name":"Default Location List","path":"./assets/location-list.json", "levels": ["county","school"]},{"id":"hospitals","name":"Hospitals","path":"./assets/locations/hospitals.json", "locationsLevels": ["clinic","ward"]}]'>

<template>

<tangy-form
Expand Down Expand Up @@ -653,7 +657,7 @@ <h1>Name: ${getValue('first_name')} ${getValue('last_name')}</h1>
</template>
</tangy-form-editor>
<script>
document.querySelector('tangy-form-editor').addEventListener('tangy-form-editor-change', event => {console.info(event.detail)})
document.querySelector('tangy-form-editor').addEventListener('tangy-form-editor-change', event => {console.info('tangy-form-editor-change event')})
</script>
</body>
</html>
5 changes: 4 additions & 1 deletion tangy-base-widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ class TangyBaseWidget extends PolymerElement {
return false;
}

// ?? So we can do event listeners on dynamic items?? Could also make form components for things like <tangy-list>.
// Use to add dynamic event listeners or make form components for things like <tangy-list>.
afterRenderEdit() {}

/*
Expand Down Expand Up @@ -917,6 +917,9 @@ class TangyBaseWidget extends PolymerElement {
.querySelector("#container")
.querySelector("tangy-form")
.addEventListener("submit", (event) => this._onSubmit());

this.afterRenderEdit();

} else if (this.mode === MODE_INFO) {
this.shadowRoot.querySelector("#container").innerHTML = this.renderInfo(
this._config
Expand Down
8 changes: 8 additions & 0 deletions tangy-form-condensed-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ class TangyFormCondensedEditor extends PolymerElement {
type: String,
value: "",
},
locationListMetadata: {
type: Object,
value: ''
}
};
}

Expand Down Expand Up @@ -112,6 +116,9 @@ class TangyFormCondensedEditor extends PolymerElement {
this.print ? "MODE_PRINT" : "MODE_INFO"
);
widgetEl.setAttribute("files-endpoint", this.filesEndpoint);
if (foundWidget.widgetName == 'tangy-location-widget') {
widgetEl.setAttribute("location-list-metadata", `${JSON.stringify(this.locationListMetadata)}`);
}
if (this.hideSkipIf) widgetEl.setAttribute("hide-skip-if", "");
if (this.hideShowIf) widgetEl.setAttribute("hide-show-if", "");
wrap(childNode, widgetEl);
Expand Down Expand Up @@ -264,6 +271,7 @@ class TangyFormCondensedEditor extends PolymerElement {
}
const addInputEl = document.createElement("tangy-form-editor-add-input");
addInputEl.setAttribute("files-endpoint", this.filesEndpoint);
addInputEl.setAttribute("location-list-metadata", `${JSON.stringify(this.locationListMetadata)}`);
if (this.hasAttribute('hide-skip-if')) addInputEl.setAttribute('hide-skip-if', '')
if (this.hasAttribute('hide-show-if')) addInputEl.setAttribute('hide-show-if', '')
if (insertAfterEl) {
Expand Down
8 changes: 8 additions & 0 deletions tangy-form-editor-add-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ class TangyFormEditorAddInput extends PolymerElement {
const wrapperEl = document.createElement(event.target.id)
wrapperEl.setAttribute('mode', 'MODE_EDIT')
wrapperEl.setAttribute('files-endpoint', this.getAttribute('files-endpoint'))

if (event.target.id == 'tangy-location-widget') {
const locationListMetadata = this.getAttribute('location-list-metadata')
if (locationListMetadata) {
wrapperEl.setAttribute("location-list-metadata", locationListMetadata);
}
}

if (this.hasAttribute('hide-skip-if')) wrapperEl.setAttribute('hide-skip-if', '')
if (this.hasAttribute('hide-show-if')) wrapperEl.setAttribute('hide-show-if', '')
this.after(wrapperEl)
Expand Down
7 changes: 6 additions & 1 deletion tangy-form-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ class TangyFormEditor extends PolymerElement {
filesEndpoint: {
type: String,
value: ''
},
locationListMetadata: {
type: Object,
value: ''
}
};
}
Expand Down Expand Up @@ -562,7 +566,8 @@ class TangyFormEditor extends PolymerElement {
this.$.container.innerHTML = ''
this.innerHTML = `
<tangy-form-item-editor
files-endpoint="${this.filesEndpoint}"
files-endpoint="${this.filesEndpoint}"
location-list-metadata='${JSON.stringify(this.locationListMetadata)}'
${this.hideSkipIf ? `hide-skip-if` : ''}
${this.hideShowIf ? `hide-show-if` : ''}
>
Expand Down
14 changes: 10 additions & 4 deletions tangy-form-item-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ class TangyFormItemEditor extends PolymerElement {
type: String,
value: "",
},
locationListMetadata: {
type: Object,
value: ''
}
};
}

Expand Down Expand Up @@ -220,10 +224,12 @@ class TangyFormItemEditor extends PolymerElement {
</div>
</paper-card>

<tangy-form-condensed-editor files-endpoint="${this.filesEndpoint}"
${this.hideSkipIf ? `hide-skip-if` : ""}
${this.hideShowIf ? `hide-show-if` : ""}
>
<tangy-form-condensed-editor
files-endpoint="${this.filesEndpoint}"
location-list-metadata='${JSON.stringify(this.locationListMetadata)}'
${this.hideSkipIf ? `hide-skip-if` : ""}
${this.hideShowIf ? `hide-show-if` : ""}
>
<template>
${this.item.template}
</template>
Expand Down
136 changes: 121 additions & 15 deletions widget/tangy-location-widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "tangy-form/input/tangy-checkbox.js";
import { TangyBaseWidget } from "../tangy-base-widget.js";

class TangyLocationWidget extends TangyBaseWidget {

get claimElement() {
return "tangy-location";
}
Expand All @@ -21,6 +22,7 @@ class TangyLocationWidget extends TangyBaseWidget {
metaDataTemplate: "",
filterByGlobal: false,
showLevels: "",
locationSrc: ""
};
}

Expand All @@ -35,6 +37,7 @@ class TangyLocationWidget extends TangyBaseWidget {
...this.upcastAdvancedAttributes(config, element),
...this.upcastUnimplementedAttributes(config, element),
metaDataTemplate: element.innerHTML,
locationListMetadata: element.locationListMetadata
};
}

Expand All @@ -50,6 +53,7 @@ class TangyLocationWidget extends TangyBaseWidget {
show-levels="${config.showLevels}"
${config.filterByGlobal ? "filter-by-global" : ""}
${config.showMetaData ? "show-meta-data" : ""}
location-src=${config.locationSrc}
>
${config.metaDataTemplate}
</tangy-location>
Expand Down Expand Up @@ -98,18 +102,33 @@ class TangyLocationWidget extends TangyBaseWidget {
<div>
${this.renderEditCoreAttributes(config)}
${this.renderEditQuestionAttributes(config)}
<tangy-checkbox name="filterByGlobal" ${
config.filterByGlobal ? 'value="on"' : ""
}>Filter by locations in the user profile?</tangy-checkbox>
<tangy-input name="showLevels" inner-label="Show levels" hint-text="e.g. county,subcounty" value="${
config.showLevels
}"></tangy-input>
<tangy-checkbox name="show-meta-data" ${
config.showMetaData ? 'value="on"' : ""
}>show meta-data</tangy-checkbox>
<tangy-input name="meta-data-template" label="Meta-data template" value="${
config.metaDataTemplate
}"></tangy-input>
<div class="container">
<h3>Select the location list to use for this input</h3>
<div>The Default Location List will be used if none is selected</div>
<div>Changing the list will clear the entry for Filter by Location</div>
<tangy-select class="location-src-select" name="location-src" value="${config.locationSrc}">
${this.renderLocationListMetadataSelect()}
</tangy-select>
</div>
<div class="container">
<h3>Select the checkboxes below to limit the levels that will appear in the list</h3>
<div>If none are selected, all levels will appear in the list</div>
<tangy-checkboxes name="showLevels" value='${this.getShowLevelTangyCheckboxesValue()}'>
${this.renderShowLevelsCheckboxes()}
</tangy-checkboxes>
</div>
<div class="container">
<h3>Choose which metadata labels will appear in the list</h3>
<div>The metadata labels are useful to provide context to the user</div>
<tangy-checkbox name="show-meta-data" ${
config.showMetaData ? 'value="on"' : ""
}>show meta-data</tangy-checkbox>
<tangy-input name="meta-data-template" label="Metadata Labels" inner-label="e.g. school,room" value="${config.metaDataTemplate}"></tangy-input>
</div>
<div class="container">
<h3>Check the box to filter the list by the user profile</h3>
<tangy-checkbox name="filterByGlobal" ${config.filterByGlobal ? 'value="on"' : ""}>Filter by locations in the user profile?</tangy-checkbox>
</div>
</div>
<div>
${this.renderEditConditionalAttributes(config)}
Expand All @@ -127,6 +146,91 @@ class TangyLocationWidget extends TangyBaseWidget {
`;
}

afterRenderEdit() {
this.shadowRoot
.querySelector("#container")
.querySelector("tangy-form")
.querySelector("tangy-form-item")
.querySelector("iron-pages")
.querySelector("tangy-select.location-src-select")
.addEventListener('change', this.onLocationSrcChange.bind(this));
}

renderLocationListMetadataSelect() {
let options = ''
let locationListMetadata = JSON.parse(this.getAttribute('location-list-metadata'))
if (locationListMetadata) {
for (let location of locationListMetadata) {
options = `${options}
<option value="${location.path}">${location.name}</option>`
}
}
return options;
}

renderShowLevelsCheckboxes() {
let options = ''
let locationListMetadata = JSON.parse(this.getAttribute('location-list-metadata'))
if (locationListMetadata) {
const locationList = Object.values(locationListMetadata).find(l => l.path == this._config.locationSrc)
for (let level of locationList.locationsLevels) {
options = `${options}
<option value="${level}">${level}</option>`
}
}
return options;
}

onLocationSrcChange(event) {
// If showLevels is set, we need to clear it when the locationSrc changes
// since the levels are probably not in the new locationSrc
if (event.target.value != this._config.locationSrc) {
this._config.locationSrc = event.target.value
this._config.showLevels = ''

// Should this be done another way?
this._render();
}
}

// converts a comma separated string of values into a tangy-checkboxes value
getShowLevelTangyCheckboxesValue() {
let values = []

if (this._config.showLevels) {
let selectedLevels = this._config.showLevels.split(',')
let locationListMetadata = JSON.parse(this.getAttribute('location-list-metadata'))
if (locationListMetadata) {
const locationList = Object.values(locationListMetadata).find(l => l.path == this._config.locationSrc)
for (let level of locationList.levels) {
values.push(
{
"name": level,
"value": selectedLevels.includes(level) ? "on" : ""
}
)
}
}
}

return JSON.stringify(values)
}

// converts a tangy-checkboxes value into a comma separated string of values
getShowLevelValueString(formEl) {
let values = []
let input = formEl.response.items[0].inputs.find(
(input) => input.name === "showLevels")
if (input) {
for (let v of input.value) {
if (v.value == 'on') {
values.push(v.name)
}
}
}
return values.join(',')
}

onSubmit(config, formEl) {
return {
...config,
Expand All @@ -136,15 +240,17 @@ class TangyLocationWidget extends TangyBaseWidget {
...this.onSubmitValidationAttributes(config, formEl),
...this.onSubmitAdvancedAttributes(config, formEl),
...this.onSubmitUnimplementedAttributes(config, formEl),
locationSrc:
formEl.response.items[0].inputs.find(
(input) => input.name === "location-src"
).value,
filterByGlobal:
formEl.response.items[0].inputs.find(
(input) => input.name === "filterByGlobal"
).value === "on"
? true
: false,
showLevels: formEl.response.items[0].inputs.find(
(input) => input.name === "showLevels"
).value,
showLevels: this.getShowLevelValueString(formEl),
showMetaData:
formEl.response.items[0].inputs.find(
(input) => input.name === "show-meta-data"
Expand Down