-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: mb-duration added to medblocks-ui
- Loading branch information
1 parent
d3d4006
commit cb865f3
Showing
6 changed files
with
238 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
import { customElement, html, property, state, css } from 'lit-element'; | ||
import SlInput from '@shoelace-style/shoelace/dist/components/input/input'; | ||
import '@shoelace-style/shoelace/dist/components/input/input'; | ||
import EhrElement from '../EhrElement'; | ||
|
||
@customElement('mb-duration') | ||
export default class MbDuration extends EhrElement { | ||
static styles = css` | ||
div { | ||
display: flex; | ||
gap: 10px; | ||
} | ||
.label { | ||
font-size: var(--sl-input-label-font-size-medium); | ||
display: inline-block; | ||
color: var(--sl-input-label-color); | ||
margin-bottom: var(--sl-spacing-xxx-small); | ||
} | ||
sl-input { | ||
width: 0; | ||
flex: 1 1 auto; | ||
} | ||
`; | ||
|
||
@property({ type: Boolean, reflect: true }) year: boolean = false; | ||
@property({ type: Boolean, reflect: true }) month: boolean = false; | ||
@property({ type: Boolean, reflect: true }) week: boolean = false; | ||
@property({ type: Boolean, reflect: true }) day: boolean = false; | ||
@property({ type: Boolean, reflect: true }) hour: boolean = false; | ||
@property({ type: Boolean, reflect: true }) minute: boolean = false; | ||
@property({ type: Boolean, reflect: true }) second: boolean = false; | ||
@property({ type: Boolean, reflect: true }) required: boolean = false; | ||
|
||
@state() _state : {[period: string]: string | undefined} = {} | ||
|
||
parsePeriod(period: string) { | ||
const [periodPart, t] = period.split('T'); | ||
const p = periodPart.replace('P', ''); | ||
this._state.year = this.getPart(p, 'Y'); | ||
this._state.month = this.getPart(p, 'M'); | ||
this._state.week = this.getPart(p, 'W'); | ||
this._state.day = this.getPart(p, 'D'); | ||
if (t) { | ||
this._state.hour = this.getPart(t, 'H'); | ||
this._state.minute = this.getPart(t, 'M'); | ||
this._state.second = this.getPart(t, 'S'); | ||
} | ||
} | ||
|
||
getPart(periodPart: string, part: string): string | undefined { | ||
const myRegexp = new RegExp(`(\\d)${part}`, 'g'); | ||
const match = myRegexp.exec(periodPart); | ||
return match ? match[1] : undefined; | ||
} | ||
|
||
serializePeriod(): string { | ||
const hour = this._state.hour ? `${this._state.hour}H` : ''; | ||
const minute = this._state.minute ? `${this._state.minute}M` : ''; | ||
const second = this._state.second ? `${this._state.second}S` : ''; | ||
const t = [hour, minute, second].join(''); | ||
|
||
const year = this._state.year ? `${this._state.year}Y` : ''; | ||
const month = this._state.month ? `${this._state.month}M` : ''; | ||
const week = this._state.week ? `${this._state.week}W` : ''; | ||
const day = this._state.day ? `${this._state.day}D` : ''; | ||
const p = [year, month, week, day].join(''); | ||
|
||
const timePart = t ? `T${t}` : ''; | ||
const periodPart = p ? `P${p}` : ''; | ||
|
||
return `${periodPart}${timePart}`; | ||
} | ||
|
||
get data() { | ||
return this.serializePeriod(); | ||
} | ||
|
||
set data(period: string) { | ||
const oldVal = this.data | ||
this.parsePeriod(period); | ||
this.requestUpdate('data',oldVal) | ||
} | ||
|
||
handleInput(value:string,e:CustomEvent){ | ||
const oldVal = this.data | ||
const target = e.target as SlInput; | ||
this._state = {...this._state, [value]: target.value}; | ||
this.requestUpdate('data', oldVal) | ||
this._mbInput.emit() | ||
} | ||
|
||
formatDuration(value: string) : string { | ||
return value.charAt(0).toUpperCase() + value.slice(1)+'s' | ||
} | ||
|
||
reportValidity() { | ||
if (this.data) { | ||
return true | ||
} else { | ||
const input = this.shadowRoot!.querySelector('sl-input') as SlInput; | ||
return input.reportValidity() | ||
} | ||
} | ||
|
||
getInputs() { | ||
const allDurations: any = { | ||
year: this.year, month: this.month, week: this.week,day: this.day, hour: this.hour, minute: this.minute, second: this.second | ||
} | ||
const durationKeys = Object.keys(allDurations) | ||
const toRender = durationKeys.every(a=>allDurations[a]===false) ? durationKeys : durationKeys | ||
.filter(a=>allDurations[a]) | ||
|
||
return toRender.map(a=>html`<sl-input | ||
id=${a} | ||
type="number" | ||
?required=${this.required} | ||
help-text=${this.formatDuration(a)} | ||
.value=${this._state[a] || ''} | ||
@sl-input=${(e: CustomEvent)=>this.handleInput(a,e)} | ||
></sl-input>`) | ||
} | ||
|
||
render(){ | ||
return html` | ||
${this.label | ||
? html`<label part="label" class="label">${this.label}</label>` | ||
: null} | ||
<div> | ||
${this.getInputs()} | ||
</div> | ||
` | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { | ||
html, | ||
fixture, | ||
expect, | ||
oneEvent, | ||
elementUpdated, | ||
} from '@open-wc/testing'; | ||
import MbDuration from '../src/medblocks/duration/duration'; | ||
import '../src/medblocks/duration/duration'; | ||
import { querySelectorAllDeep } from 'query-selector-shadow-dom'; | ||
import { SlInput } from '@shoelace-style/shoelace'; | ||
|
||
describe('MbDuration', () => { | ||
it('emits data on input', async () => { | ||
const mbDuration = await fixture<MbDuration>( | ||
html`<mb-duration year=${true} label="Year"></mb-duration>` | ||
); | ||
const year = querySelectorAllDeep('input') as SlInput[]; | ||
setTimeout(() => { | ||
year[0].value = '2'; | ||
year[0].dispatchEvent(new Event('input')); | ||
}); | ||
const event: any = await oneEvent(mbDuration, 'mb-input'); | ||
expect(event.target.data).to.eq('P2Y'); | ||
}); | ||
it('changes input on setting data', async () => { | ||
const mbDuration = await fixture<MbDuration>( | ||
html`<mb-duration year label="Year"></mb-duration>` | ||
); | ||
const year = querySelectorAllDeep('input') as SlInput[]; | ||
setTimeout(()=>{ | ||
mbDuration.data = 'P3Y'; | ||
},0) | ||
await oneEvent(mbDuration, 'mb-input'); | ||
await elementUpdated(mbDuration); | ||
expect(year[0].value).to.eq('3'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import '../../medblocks' | ||
import { expect } from '@open-wc/testing' | ||
import { elementUpdated, fixture } from '@open-wc/testing-helpers' | ||
import { html } from 'lit-html' | ||
import { querySelectorDeep } from 'query-selector-shadow-dom' | ||
import MbForm from '../../src/medblocks/form/form' | ||
|
||
|
||
|
||
describe('duration validation test',()=>{ | ||
it('empty',async ()=>{ | ||
const form = await fixture<MbForm>( | ||
html` | ||
<mb-form> | ||
<mb-duration year path="test/1"></mb-duration> | ||
</mb-form> | ||
` | ||
) | ||
await elementUpdated(form); | ||
expect(form.validate()).to.be.true | ||
}) | ||
it('data',async ()=>{ | ||
const form = await fixture<MbForm>( | ||
html` | ||
<mb-form> | ||
<mb-duration year path="test/1"></mb-duration> | ||
</mb-form> | ||
` | ||
) | ||
const duration = querySelectorDeep('mb-duration') as any; | ||
duration.data = 'P2Y3MT2H' | ||
await elementUpdated(form); | ||
expect(form.validate()).to.be.true | ||
}) | ||
it('required but empty',async ()=>{ | ||
const form = await fixture<MbForm>( | ||
html` | ||
<mb-form> | ||
<mb-duration year required path="test/1"></mb-duration> | ||
</mb-form> | ||
` | ||
) | ||
await elementUpdated(form) | ||
expect(form.validate()).to.be.false | ||
}) | ||
it('required with data',async ()=>{ | ||
const form = await fixture<MbForm>( | ||
html` | ||
<mb-form> | ||
<mb-duration year required path="test/1"></mb-duration> | ||
</mb-form> | ||
` | ||
) | ||
const duration = querySelectorDeep('mb-duration') as any; | ||
duration.data = 'PT2H' | ||
await elementUpdated(form) | ||
expect(form.validate()).to.be.true | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters