From f1ca709f25500588c814aedacba45b08cd756cc2 Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Wed, 8 May 2019 06:43:48 +0200 Subject: [PATCH 01/17] Add test for missing mucus vaues --- test/sensiplan-mucus.spec.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/sensiplan-mucus.spec.js b/test/sensiplan-mucus.spec.js index accbfe3..3cdb8c1 100644 --- a/test/sensiplan-mucus.spec.js +++ b/test/sensiplan-mucus.spec.js @@ -7,6 +7,11 @@ chai.use(dirtyChai) import getSensiplanMucus from '../lib/nfp-mucus' describe('getSensiplanMucus', () => { + it('returns null if there is no value for feeling or texture', () => { + expect(getSensiplanMucus()).to.be.null() + expect(getSensiplanMucus(undefined, 3)).to.be.null() + expect(getSensiplanMucus(2, undefined)).to.be.null() + }) describe('results in t for:', () => { it('dry feeling and no texture', function () { From 6402370eafb7142af12448ba44cdb6a8390317ad Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Wed, 8 May 2019 06:44:14 +0200 Subject: [PATCH 02/17] Don't compute nfp mucus value when data missing --- lib/nfp-mucus.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/nfp-mucus.js b/lib/nfp-mucus.js index 27e1590..1a8e8a9 100644 --- a/lib/nfp-mucus.js +++ b/lib/nfp-mucus.js @@ -1,4 +1,7 @@ export default function (feeling, texture) { + + if (typeof feeling != 'number' || typeof texture != 'number') return null + const feelingMapping = { 0: 0, 1: 1, From c6790fe27156d36a798f5fce1906099883d00396 Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Sat, 11 May 2019 12:05:44 +0200 Subject: [PATCH 03/17] Add migration making mucus and cervix values optional --- db/schemas/4.js | 171 ++++++++++++++++++++++++++++++++++++++++++++ db/schemas/index.js | 3 +- 2 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 db/schemas/4.js diff --git a/db/schemas/4.js b/db/schemas/4.js new file mode 100644 index 0000000..166a2e0 --- /dev/null +++ b/db/schemas/4.js @@ -0,0 +1,171 @@ +const TemperatureSchema = { + name: 'Temperature', + properties: { + value: 'double', + exclude: 'bool', + time: { + type: 'string', + optional: true + }, + note: { + type: 'string', + optional: true + } + } +} + +const BleedingSchema = { + name: 'Bleeding', + properties: { + value: 'int', + exclude: 'bool' + } +} + +const MucusSchema = { + name: 'Mucus', + properties: { + feeling: { type: 'int', optional: true }, + texture: { type: 'int', optional: true }, + value: { type: 'int', optional: true }, + exclude: 'bool' + } +} + +const CervixSchema = { + name: 'Cervix', + properties: { + opening: { type: 'int', optional: true }, + firmness: { type: 'int', optional: true }, + position: {type: 'int', optional: true }, + exclude: 'bool' + } +} + +const NoteSchema = { + name: 'Note', + properties: { + value: 'string' + } +} + +const DesireSchema = { + name: 'Desire', + properties: { + value: 'int' + } +} + +const SexSchema = { + name: 'Sex', + properties: { + solo: { type: 'bool', optional: true }, + partner: { type: 'bool', optional: true }, + condom: { type: 'bool', optional: true }, + pill: { type: 'bool', optional: true }, + iud: { type: 'bool', optional: true }, + patch: { type: 'bool', optional: true }, + ring: { type: 'bool', optional: true }, + implant: { type: 'bool', optional: true }, + diaphragm: { type: 'bool', optional: true }, + none: { type: 'bool', optional: true }, + other: { type: 'bool', optional: true }, + note: { type: 'string', optional: true } + } +} + +const PainSchema = { + name: 'Pain', + properties: { + cramps: { type: 'bool', optional: true }, + ovulationPain: { type: 'bool', optional: true }, + headache: { type: 'bool', optional: true }, + backache: { type: 'bool', optional: true }, + nausea: { type: 'bool', optional: true }, + tenderBreasts: { type: 'bool', optional: true }, + migraine: { type: 'bool', optional: true }, + other: { type: 'bool', optional: true }, + note: { type: 'string', optional: true } + } +} + +const MoodSchema = { + name: 'Mood', + properties: { + happy: { type: 'bool', optional: true }, + sad: { type: 'bool', optional: true }, + stressed: { type: 'bool', optional: true }, + balanced: { type: 'bool', optional: true }, + fine: { type: 'bool', optional: true }, + anxious: { type: 'bool', optional: true }, + energetic: { type: 'bool', optional: true }, + fatigue: { type: 'bool', optional: true }, + angry: { type: 'bool', optional: true }, + other: { type: 'bool', optional: true }, + note: { type: 'string', optional: true } + } +} + +const CycleDaySchema = { + name: 'CycleDay', + primaryKey: 'date', + properties: { + date: 'string', + temperature: { + type: 'Temperature', + optional: true + }, + isCycleStart: 'bool', + bleeding: { + type: 'Bleeding', + optional: true + }, + mucus: { + type: 'Mucus', + optional: true + }, + cervix: { + type: 'Cervix', + optional: true + }, + note: { + type: 'Note', + optional: true + }, + desire: { + type: 'Desire', + optional: true + }, + sex: { + type: 'Sex', + optional: true + }, + pain: { + type: 'Pain', + optional: true + }, + mood: { + type: 'Mood', + optional: true + } + } +} + +export default { + schema: [ + CycleDaySchema, + TemperatureSchema, + BleedingSchema, + MucusSchema, + CervixSchema, + NoteSchema, + DesireSchema, + SexSchema, + PainSchema, + MoodSchema + ], + schemaVersion: 4, + migration: (oldRealm) => { + if (oldRealm.schemaVersion >= 4) return + } +} diff --git a/db/schemas/index.js b/db/schemas/index.js index ed14e67..4530908 100644 --- a/db/schemas/index.js +++ b/db/schemas/index.js @@ -2,5 +2,6 @@ import schema0 from './0.js' import schema1 from './1.js' import schema2 from './2.js' import schema3 from './3.js' +import schema4 from './4.js' -export default [schema0, schema1, schema2, schema3] \ No newline at end of file +export default [schema0, schema1, schema2, schema3, schema4] \ No newline at end of file From 8d6f5d637b5d0e786399c6d7ca7af2adedcd458a Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Sat, 11 May 2019 12:42:23 +0200 Subject: [PATCH 04/17] Update sympto --- package-lock.json | 47 ++++++++++++++--------------------------------- package.json | 2 +- 2 files changed, 15 insertions(+), 34 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7529c9f..66701f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3229,8 +3229,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.2.0", @@ -3248,13 +3247,11 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3267,18 +3264,15 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", - "bundled": true, - "optional": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -3381,8 +3375,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -3392,7 +3385,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3405,20 +3397,17 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true, - "optional": true + "bundled": true }, "minipass": { "version": "2.3.5", "bundled": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3435,7 +3424,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -3508,8 +3496,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -3519,7 +3506,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3595,8 +3581,7 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -3626,7 +3611,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3644,7 +3628,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3683,13 +3666,11 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true }, "yallist": { "version": "3.0.3", - "bundled": true, - "optional": true + "bundled": true } } }, @@ -8097,9 +8078,9 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, "sympto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sympto/-/sympto-1.0.1.tgz", - "integrity": "sha512-wLDpugvScuXhSBhgJHZTGU9gTd5uDnuZDJuNz7aUSj1N28VOe2RhKwMF4RLwjy3s6i+BG1Lfa3uckNPCFPkUvA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/sympto/-/sympto-1.0.4.tgz", + "integrity": "sha512-FSdSwPeE3BKvnJlPkHzVusGMTz4r6dW2eEEJbgPrgdkmPWmAFWTD7Hf7OhqQSbTLjiZY7jBeWDWuizb4UZMk1g==", "requires": { "js-joda": "^1.9.2" } diff --git a/package.json b/package.json index 5017dfd..374ce70 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "react-native-share": "^1.1.3", "react-native-vector-icons": "^5.0.0", "realm": "^2.22.0", - "sympto": "^1.0.0" + "sympto": "^1.0.4" }, "devDependencies": { "@babel/core": "^7.2.2", From ca6818635153c2466b85238bf6086ff5de6fae2f Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Sat, 11 May 2019 12:50:31 +0200 Subject: [PATCH 05/17] Filter out incomplete cervix value days in sympto adapter --- lib/sympto-adapter.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/sympto-adapter.js b/lib/sympto-adapter.js index 2991da9..f2fb1c0 100644 --- a/lib/sympto-adapter.js +++ b/lib/sympto-adapter.js @@ -108,7 +108,11 @@ function formatCycleForSympto(cycle) { if (day[symptomName] && day[symptomName].exclude) { delete day[symptomName] } - }); + }) + // remove days with incomplete cervix values + if (hasIncompleteCervixValue(day)) { + delete day.cervix + } // change format ['bleeding', 'temperature', 'mucus'].forEach(symptomName => { if (day[symptomName]) day[symptomName] = day[symptomName].value @@ -119,4 +123,8 @@ function formatCycleForSympto(cycle) { // we get earliest last, but sympto wants earliest first formatted.reverse() return formatted +} + +function hasIncompleteCervixValue(day) { + return day.cervix && (typeof day.cervix.opening != 'number' || typeof day.cervix.firmness != 'number') } \ No newline at end of file From 9fd17d769eacac0cf46a575a01612a8ce48b5baf Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Sat, 11 May 2019 14:30:27 +0200 Subject: [PATCH 06/17] Make saving incomplete value possible --- .../symptoms/action-button-footer.js | 30 ++++--------------- components/cycle-day/symptoms/cervix.js | 5 +--- components/cycle-day/symptoms/mucus.js | 3 -- 3 files changed, 7 insertions(+), 31 deletions(-) diff --git a/components/cycle-day/symptoms/action-button-footer.js b/components/cycle-day/symptoms/action-button-footer.js index 28b78fb..f4b0618 100644 --- a/components/cycle-day/symptoms/action-button-footer.js +++ b/components/cycle-day/symptoms/action-button-footer.js @@ -1,7 +1,6 @@ import React, { Component } from 'react' import { - View, TouchableOpacity, Text, Alert, ToastAndroid -} from 'react-native' + View, TouchableOpacity, Text, Alert} from 'react-native' import Icon from 'react-native-vector-icons/MaterialCommunityIcons' import { saveSymptom } from '../../../db' import styles, {iconStyles} from '../../../styles' @@ -15,7 +14,6 @@ export default class ActionButtonFooter extends Component { currentSymptomValue, date, saveAction, - saveDisabled, navigate, autoShowDayView = true} = this.props @@ -47,40 +45,24 @@ export default class ActionButtonFooter extends Component { }, { title: labels.save, action: () => { - if(saveDisabled) { - ToastAndroid.show(labels.disabledInfo, ToastAndroid.LONG) - } else { - saveAction() - if (autoShowDayView) navigateToOverView() - } + saveAction() + if (autoShowDayView) navigateToOverView() }, - disabledCondition: saveDisabled, icon: 'content-save-outline' } ] return ( - - {buttons.map(({ title, action, disabledCondition, icon }, i) => { + + {buttons.map(({ title, action, icon }, i) => { const textStyle = [styles.menuText] - if (disabledCondition) { - textStyle.push(styles.menuTextInActive) - } - const iconStyle = disabledCondition ? - Object.assign( - {}, - iconStyles.menuIcon, - iconStyles.menuIconInactive - ) - : - iconStyles.menuIcon return ( - + {title.toLowerCase()} diff --git a/components/cycle-day/symptoms/cervix.js b/components/cycle-day/symptoms/cervix.js index d0e3e07..c47cfe0 100644 --- a/components/cycle-day/symptoms/cervix.js +++ b/components/cycle-day/symptoms/cervix.js @@ -10,7 +10,6 @@ import { cervix as labels } from '../../../i18n/en/cycle-day' import ActionButtonFooter from './action-button-footer' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' -import { ActionHint } from '../../app-text' export default class Cervix extends Component { constructor(props) { @@ -36,7 +35,7 @@ export default class Cervix extends Component { { label: labels.position.categories[1], value: 1 }, { label: labels.position.categories[2], value: 2 } ] - const mandatoryNotCompletedYet = typeof this.state.opening != 'number' || typeof this.state.firmness != 'number' + const mandatoryNotCompleted = typeof this.state.opening != 'number' || typeof this.state.firmness != 'number' return ( @@ -83,7 +82,6 @@ export default class Cervix extends Component { /> - {labels.actionHint} diff --git a/components/cycle-day/symptoms/mucus.js b/components/cycle-day/symptoms/mucus.js index 6e2d2ce..ff5865e 100644 --- a/components/cycle-day/symptoms/mucus.js +++ b/components/cycle-day/symptoms/mucus.js @@ -11,7 +11,6 @@ import computeNfpValue from '../../../lib/nfp-mucus' import ActionButtonFooter from './action-button-footer' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' -import { ActionHint } from '../../app-text' export default class Mucus extends Component { constructor(props) { @@ -71,7 +70,6 @@ export default class Mucus extends Component { /> - {labels.actionHint} From d322e557a350c4d455b3a15baa5465c45204ac32 Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Sat, 11 May 2019 14:45:25 +0200 Subject: [PATCH 07/17] Remove unused line --- components/cycle-day/symptoms/bleeding.js | 1 - components/cycle-day/symptoms/cervix.js | 1 - components/cycle-day/symptoms/desire.js | 1 - components/cycle-day/symptoms/mucus.js | 1 - components/cycle-day/symptoms/note.js | 1 - 5 files changed, 5 deletions(-) diff --git a/components/cycle-day/symptoms/bleeding.js b/components/cycle-day/symptoms/bleeding.js index 3f7df98..faebf1b 100644 --- a/components/cycle-day/symptoms/bleeding.js +++ b/components/cycle-day/symptoms/bleeding.js @@ -16,7 +16,6 @@ export default class Bleeding extends Component { super(props) const cycleDay = props.cycleDay this.bleeding = cycleDay && cycleDay.bleeding - this.makeActionButtons = props.makeActionButtons this.state = { currentValue: this.bleeding && this.bleeding.value, exclude: this.bleeding ? this.bleeding.exclude : false diff --git a/components/cycle-day/symptoms/cervix.js b/components/cycle-day/symptoms/cervix.js index c47cfe0..457c914 100644 --- a/components/cycle-day/symptoms/cervix.js +++ b/components/cycle-day/symptoms/cervix.js @@ -16,7 +16,6 @@ export default class Cervix extends Component { super(props) const cycleDay = props.cycleDay this.cervix = cycleDay && cycleDay.cervix - this.makeActionButtons = props.makeActionButtons this.state = this.cervix ? this.cervix : {} } diff --git a/components/cycle-day/symptoms/desire.js b/components/cycle-day/symptoms/desire.js index cc3b536..6c20bf0 100644 --- a/components/cycle-day/symptoms/desire.js +++ b/components/cycle-day/symptoms/desire.js @@ -15,7 +15,6 @@ export default class Desire extends Component { super(props) const cycleDay = props.cycleDay this.desire = cycleDay && cycleDay.desire - this.makeActionButtons = props.makeActionButtons const desireValue = this.desire && this.desire.value this.state = { currentValue: desireValue } } diff --git a/components/cycle-day/symptoms/mucus.js b/components/cycle-day/symptoms/mucus.js index ff5865e..e46acb2 100644 --- a/components/cycle-day/symptoms/mucus.js +++ b/components/cycle-day/symptoms/mucus.js @@ -17,7 +17,6 @@ export default class Mucus extends Component { super(props) const cycleDay = props.cycleDay this.mucus = cycleDay && cycleDay.mucus - this.makeActionButtons = props.makeActionButtons this.state = this.mucus ? this.mucus : {} } diff --git a/components/cycle-day/symptoms/note.js b/components/cycle-day/symptoms/note.js index 491061b..4df8a55 100644 --- a/components/cycle-day/symptoms/note.js +++ b/components/cycle-day/symptoms/note.js @@ -17,7 +17,6 @@ export default class Note extends Component { super(props) const cycleDay = props.cycleDay this.note = cycleDay && cycleDay.note - this.makeActionButtons = props.makeActionButtons this.state = { currentValue: this.note && this.note.value || '' From 2528c033157e524e9d4abf8c66c43f6d6d1b7217 Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Sat, 11 May 2019 16:23:26 +0200 Subject: [PATCH 08/17] Remove save button from footer --- components/cycle-day/symptoms/action-button-footer.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/components/cycle-day/symptoms/action-button-footer.js b/components/cycle-day/symptoms/action-button-footer.js index f4b0618..37526f3 100644 --- a/components/cycle-day/symptoms/action-button-footer.js +++ b/components/cycle-day/symptoms/action-button-footer.js @@ -13,9 +13,8 @@ export default class ActionButtonFooter extends Component { symptom, currentSymptomValue, date, - saveAction, navigate, - autoShowDayView = true} + } = this.props const navigateToOverView = () => navigate('CycleDay', {date}) const buttons = [ @@ -42,14 +41,6 @@ export default class ActionButtonFooter extends Component { (Object.values(currentSymptomValue).every(x => !x) && currentSymptomValue.constructor === Object) ), icon: 'delete-outline' - }, { - title: labels.save, - action: () => { - saveAction() - if (autoShowDayView) navigateToOverView() - - }, - icon: 'content-save-outline' } ] return ( From 08fd3afc3444e38bf6f237cfe1e9b39e1dd32e8c Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Sat, 11 May 2019 17:42:57 +0200 Subject: [PATCH 09/17] Add symptom view component with back button listener --- components/cycle-day/symptoms/bleeding.js | 19 +++++++------ components/cycle-day/symptoms/cervix.js | 16 +++++++++-- components/cycle-day/symptoms/desire.js | 14 ++++++---- components/cycle-day/symptoms/info-symptom.js | 5 ++-- components/cycle-day/symptoms/mood.js | 22 ++++++++------- components/cycle-day/symptoms/mucus.js | 28 ++++++++++--------- components/cycle-day/symptoms/note.js | 16 ++++++----- components/cycle-day/symptoms/pain.js | 20 +++++++------ components/cycle-day/symptoms/sex.js | 20 +++++++------ components/cycle-day/symptoms/symptom-view.js | 13 +++++++++ components/cycle-day/symptoms/temperature.js | 12 +++++--- 11 files changed, 113 insertions(+), 72 deletions(-) create mode 100644 components/cycle-day/symptoms/symptom-view.js diff --git a/components/cycle-day/symptoms/bleeding.js b/components/cycle-day/symptoms/bleeding.js index faebf1b..890df1b 100644 --- a/components/cycle-day/symptoms/bleeding.js +++ b/components/cycle-day/symptoms/bleeding.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React from 'react' import { View, Switch, @@ -10,8 +10,9 @@ import { bleeding } from '../../../i18n/en/cycle-day' import ActionButtonFooter from './action-button-footer' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' +import SymptomView from './symptom-view' -export default class Bleeding extends Component { +export default class Bleeding extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -22,6 +23,13 @@ export default class Bleeding extends Component { } } + save() { + saveSymptom('bleeding', this.props.date, { + value: this.state.currentValue, + exclude: this.state.exclude + }) + } + render() { const bleedingRadioProps = [ { label: bleeding.labels[0], value: 0 }, @@ -59,13 +67,6 @@ export default class Bleeding extends Component { symptom='bleeding' date={this.props.date} currentSymptomValue={this.bleeding} - saveAction={() => { - saveSymptom('bleeding', this.props.date, { - value: this.state.currentValue, - exclude: this.state.exclude - }) - }} - saveDisabled={typeof this.state.currentValue != 'number'} navigate={this.props.navigate} /> diff --git a/components/cycle-day/symptoms/cervix.js b/components/cycle-day/symptoms/cervix.js index 457c914..811cb2e 100644 --- a/components/cycle-day/symptoms/cervix.js +++ b/components/cycle-day/symptoms/cervix.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React from 'react' import { View, Switch, @@ -10,15 +10,25 @@ import { cervix as labels } from '../../../i18n/en/cycle-day' import ActionButtonFooter from './action-button-footer' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' +import SymptomView from './symptom-view' -export default class Cervix extends Component { +export default class Cervix extends SymptomView { constructor(props) { - super(props) + super() const cycleDay = props.cycleDay this.cervix = cycleDay && cycleDay.cervix this.state = this.cervix ? this.cervix : {} } + save() { + saveSymptom('cervix', this.props.date, { + opening: this.state.opening, + firmness: this.state.firmness, + position: this.state.position, + exclude: Boolean(this.state.exclude) + }) + } + render() { const cervixOpeningRadioProps = [ { label: labels.opening.categories[0], value: 0 }, diff --git a/components/cycle-day/symptoms/desire.js b/components/cycle-day/symptoms/desire.js index 6c20bf0..6b690db 100644 --- a/components/cycle-day/symptoms/desire.js +++ b/components/cycle-day/symptoms/desire.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React from 'react' import { View, ScrollView @@ -9,16 +9,21 @@ import { intensity, desire } from '../../../i18n/en/cycle-day' import ActionButtonFooter from './action-button-footer' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' +import SymptomView from './symptom-view' -export default class Desire extends Component { +export default class Desire extends SymptomView { constructor(props) { - super(props) + super() const cycleDay = props.cycleDay this.desire = cycleDay && cycleDay.desire const desireValue = this.desire && this.desire.value this.state = { currentValue: desireValue } } + save() { + saveSymptom('desire', this.props.date, { value: this.state.currentValue }) + } + render() { const desireRadioProps = [ { label: intensity[0], value: 0 }, @@ -43,9 +48,6 @@ export default class Desire extends Component { symptom='desire' date={this.props.date} currentSymptomValue={this.desire} - saveAction={() => { - saveSymptom('desire', this.props.date, { value: this.state.currentValue }) - }} saveDisabled={typeof this.state.currentValue != 'number'} navigate={this.props.navigate} /> diff --git a/components/cycle-day/symptoms/info-symptom.js b/components/cycle-day/symptoms/info-symptom.js index 951ed47..2c75e88 100644 --- a/components/cycle-day/symptoms/info-symptom.js +++ b/components/cycle-day/symptoms/info-symptom.js @@ -1,11 +1,12 @@ -import React, { Component } from 'react' +import React from 'react' import { ScrollView } from 'react-native' import AppText from '../../app-text' import labels from '../../../i18n/en/symptom-info.js' import FramedSegment from '../../framed-segment' import styles from '../../../styles/index' +import SymptomView from './symptom-view' -export default class InfoSymptom extends Component { +export default class InfoSymptom extends SymptomView { render() { const symptomView = this.props.symptomView const symptomMapping = { diff --git a/components/cycle-day/symptoms/mood.js b/components/cycle-day/symptoms/mood.js index 903d5d9..bbaa2e4 100644 --- a/components/cycle-day/symptoms/mood.js +++ b/components/cycle-day/symptoms/mood.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React from 'react' import { ScrollView, TextInput, @@ -10,10 +10,11 @@ import ActionButtonFooter from './action-button-footer' import SelectBoxGroup from '../select-box-group' import SymptomSection from './symptom-section' import styles from '../../../styles' +import SymptomView from './symptom-view' -export default class Mood extends Component { +export default class Mood extends SymptomView { constructor(props) { - super(props) + super() const cycleDay = props.cycleDay if (cycleDay && cycleDay.mood) { this.state = Object.assign({}, cycleDay.mood) @@ -25,6 +26,14 @@ export default class Mood extends Component { } } + save() { + const copyOfState = Object.assign({}, this.state) + if (!copyOfState.other) { + copyOfState.note = null + } + saveSymptom('mood', this.props.date, copyOfState) + } + toggleState = (key) => { const curr = this.state[key] this.setState({[key]: !curr}) @@ -62,13 +71,6 @@ export default class Mood extends Component { symptom='mood' date={this.props.date} currentSymptomValue={this.state} - saveAction={() => { - const copyOfState = Object.assign({}, this.state) - if (!copyOfState.other) { - copyOfState.note = null - } - saveSymptom('mood', this.props.date, copyOfState) - }} saveDisabled={Object.values(this.state).every(value => !value)} navigate={this.props.navigate} /> diff --git a/components/cycle-day/symptoms/mucus.js b/components/cycle-day/symptoms/mucus.js index e46acb2..16e5529 100644 --- a/components/cycle-day/symptoms/mucus.js +++ b/components/cycle-day/symptoms/mucus.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React from 'react' import { View, Switch, @@ -11,15 +11,27 @@ import computeNfpValue from '../../../lib/nfp-mucus' import ActionButtonFooter from './action-button-footer' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' +import SymptomView from './symptom-view' -export default class Mucus extends Component { +export default class Mucus extends SymptomView { constructor(props) { - super(props) + super() const cycleDay = props.cycleDay this.mucus = cycleDay && cycleDay.mucus this.state = this.mucus ? this.mucus : {} } + save() { + const feeling = this.state.feeling + const texture = this.state.texture + saveSymptom('mucus', this.props.date, { + feeling, + texture, + value: computeNfpValue(feeling, texture), + exclude: Boolean(this.state.exclude) + }) + } + render() { const mucusFeeling = [ { label: labels.feeling.categories[0], value: 0 }, @@ -73,16 +85,6 @@ export default class Mucus extends Component { symptom='mucus' date={this.props.date} currentSymptomValue={this.mucus} - saveAction={() => { - const feeling = this.state.feeling - const texture = this.state.texture - saveSymptom('mucus', this.props.date, { - feeling, - texture, - value: computeNfpValue(feeling, texture), - exclude: Boolean(this.state.exclude) - }) - }} navigate={this.props.navigate} /> diff --git a/components/cycle-day/symptoms/note.js b/components/cycle-day/symptoms/note.js index 4df8a55..06ee83a 100644 --- a/components/cycle-day/symptoms/note.js +++ b/components/cycle-day/symptoms/note.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React from 'react' import { View, ScrollView, @@ -11,8 +11,9 @@ import ActionButtonFooter from './action-button-footer' import SymptomSection from './symptom-section' import { noteExplainer } from '../../../i18n/en/cycle-day' import { shared as sharedLabels } from '../../../i18n/en/labels' +import SymptomView from './symptom-view' -export default class Note extends Component { +export default class Note extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -23,6 +24,12 @@ export default class Note extends Component { } } + save() { + saveSymptom('note', this.props.date, { + value: this.state.currentValue + }) + } + render() { return ( @@ -45,11 +52,6 @@ export default class Note extends Component { symptom='note' date={this.props.date} currentSymptomValue={this.note} - saveAction={() => { - saveSymptom('note', this.props.date, { - value: this.state.currentValue - }) - }} saveDisabled={!this.state.currentValue} navigate={this.props.navigate} /> diff --git a/components/cycle-day/symptoms/pain.js b/components/cycle-day/symptoms/pain.js index 7a2d9e3..48eb15b 100644 --- a/components/cycle-day/symptoms/pain.js +++ b/components/cycle-day/symptoms/pain.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React from 'react' import { ScrollView, TextInput, @@ -11,8 +11,9 @@ import ActionButtonFooter from './action-button-footer' import SelectBoxGroup from '../select-box-group' import SymptomSection from './symptom-section' import styles from '../../../styles' +import SymptomView from './symptom-view' -export default class Pain extends Component { +export default class Pain extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -26,6 +27,14 @@ export default class Pain extends Component { } } + save() { + const copyOfState = Object.assign({}, this.state) + if (!copyOfState.other) { + copyOfState.note = null + } + saveSymptom('pain', this.props.date, copyOfState) + } + toggleState = (key) => { const curr = this.state[key] this.setState({[key]: !curr}) @@ -63,13 +72,6 @@ export default class Pain extends Component { symptom='pain' date={this.props.date} currentSymptomValue={this.state} - saveAction={() => { - const copyOfState = Object.assign({}, this.state) - if (!copyOfState.other) { - copyOfState.note = null - } - saveSymptom('pain', this.props.date, copyOfState) - }} saveDisabled={Object.values(this.state).every(value => !value)} navigate={this.props.navigate} /> diff --git a/components/cycle-day/symptoms/sex.js b/components/cycle-day/symptoms/sex.js index 0e5649b..4d5c8e6 100644 --- a/components/cycle-day/symptoms/sex.js +++ b/components/cycle-day/symptoms/sex.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React from 'react' import { TextInput, View, @@ -11,8 +11,9 @@ import { shared as sharedLabels } from '../../../i18n/en/labels' import ActionButtonFooter from './action-button-footer' import SelectBoxGroup from '../select-box-group' import SymptomSection from './symptom-section' +import SymptomView from './symptom-view' -export default class Sex extends Component { +export default class Sex extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -26,6 +27,14 @@ export default class Sex extends Component { if (this.state.note) this.state.other = true } + save() { + const copyOfState = Object.assign({}, this.state) + if (!copyOfState.other) { + copyOfState.note = null + } + saveSymptom('sex', this.props.date, copyOfState) + } + toggleState = (key) => { const curr = this.state[key] this.setState({[key]: !curr}) @@ -75,13 +84,6 @@ export default class Sex extends Component { symptom='sex' date={this.props.date} currentSymptomValue={this.state} - saveAction={() => { - const copyOfState = Object.assign({}, this.state) - if (!copyOfState.other) { - copyOfState.note = null - } - saveSymptom('sex', this.props.date, copyOfState) - }} saveDisabled={Object.values(this.state).every(value => !value)} navigate={this.props.navigate} /> diff --git a/components/cycle-day/symptoms/symptom-view.js b/components/cycle-day/symptoms/symptom-view.js new file mode 100644 index 0000000..4110d99 --- /dev/null +++ b/components/cycle-day/symptoms/symptom-view.js @@ -0,0 +1,13 @@ +import { Component } from 'react' +import { BackHandler } from 'react-native' + +export default class SymptomView extends Component { + constructor() { + super() + this.backHandler = BackHandler.addEventListener('hardwareBackPress', this.save.bind(this)) + } + + componentWillUnmount() { + this.backHandler.remove() + } +} \ No newline at end of file diff --git a/components/cycle-day/symptoms/temperature.js b/components/cycle-day/symptoms/temperature.js index 6ebada9..f9de279 100644 --- a/components/cycle-day/symptoms/temperature.js +++ b/components/cycle-day/symptoms/temperature.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React from 'react' import { View, Switch, @@ -20,10 +20,11 @@ import config from '../../../config' import AppTextInput from '../../app-text-input' import AppText from '../../app-text' import SymptomSection from './symptom-section' +import SymptomView from './symptom-view' const minutes = ChronoUnit.MINUTES -export default class Temp extends Component { +export default class Temp extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -45,7 +46,7 @@ export default class Temp extends Component { this.state.temperature = `${this.state.temperature}.0` } } else { - const prevTemp = getPreviousTemperature(this.props.date) + const prevTemp = getPreviousTemperature(props.date) if (prevTemp) { this.state.temperature = prevTemp.toString() this.state.isSuggestion = true @@ -53,6 +54,10 @@ export default class Temp extends Component { } } + save() { + this.checkRangeAndSave() + } + saveTemperature = () => { const dataToSave = { value: Number(this.state.temperature), @@ -182,7 +187,6 @@ export default class Temp extends Component { symptom='temperature' date={this.props.date} currentSymptomValue={this.temperature} - saveAction={() => this.checkRangeAndSave()} saveDisabled={ this.state.temperature === '' || isNaN(Number(this.state.temperature)) || From ecf3ebf16d449cbc20fbcc48e0baa069ecd3c221 Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Sun, 12 May 2019 12:47:05 +0200 Subject: [PATCH 10/17] When nothing entered, delete entry --- components/cycle-day/symptoms/bleeding.js | 11 +++++++--- components/cycle-day/symptoms/cervix.js | 22 +++++++++---------- components/cycle-day/symptoms/desire.js | 13 +++++++---- components/cycle-day/symptoms/mood.js | 14 ++++++++---- components/cycle-day/symptoms/mucus.js | 15 +++++++++---- components/cycle-day/symptoms/note.js | 10 +++++++-- components/cycle-day/symptoms/pain.js | 12 ++++++++-- components/cycle-day/symptoms/sex.js | 13 ++++++++--- components/cycle-day/symptoms/symptom-view.js | 15 +++++++++++-- components/cycle-day/symptoms/temperature.js | 15 +++++++++---- 10 files changed, 101 insertions(+), 39 deletions(-) diff --git a/components/cycle-day/symptoms/bleeding.js b/components/cycle-day/symptoms/bleeding.js index 890df1b..ddb5795 100644 --- a/components/cycle-day/symptoms/bleeding.js +++ b/components/cycle-day/symptoms/bleeding.js @@ -5,7 +5,6 @@ import { ScrollView } from 'react-native' import styles from '../../../styles' -import { saveSymptom } from '../../../db' import { bleeding } from '../../../i18n/en/cycle-day' import ActionButtonFooter from './action-button-footer' import SelectTabGroup from '../select-tab-group' @@ -23,8 +22,14 @@ export default class Bleeding extends SymptomView { } } - save() { - saveSymptom('bleeding', this.props.date, { + symptomName = 'bleeding' + + onBackButtonPress() { + if (typeof this.state.currentValue != 'number') { + this.deleteSymptomEntry() + return + } + this.saveSymptomEntry({ value: this.state.currentValue, exclude: this.state.exclude }) diff --git a/components/cycle-day/symptoms/cervix.js b/components/cycle-day/symptoms/cervix.js index 811cb2e..8ff4385 100644 --- a/components/cycle-day/symptoms/cervix.js +++ b/components/cycle-day/symptoms/cervix.js @@ -14,14 +14,22 @@ import SymptomView from './symptom-view' export default class Cervix extends SymptomView { constructor(props) { - super() + super(props) const cycleDay = props.cycleDay this.cervix = cycleDay && cycleDay.cervix this.state = this.cervix ? this.cervix : {} } - save() { - saveSymptom('cervix', this.props.date, { + symptomName = 'cervix' + + onBackButtonPress() { + const nothingEntered = ['opening', 'firmness', 'position'].every(val => typeof this.state[val] != 'number') + if (nothingEntered) { + this.deleteSymptomEntry() + return + } + + this.saveSymptomEntry({ opening: this.state.opening, firmness: this.state.firmness, position: this.state.position, @@ -95,14 +103,6 @@ export default class Cervix extends SymptomView { symptom='cervix' date={this.props.date} currentSymptomValue={this.cervix} - saveAction={() => { - saveSymptom('cervix', this.props.date, { - opening: this.state.opening, - firmness: this.state.firmness, - position: this.state.position, - exclude: Boolean(this.state.exclude) - }) - }} navigate={this.props.navigate} /> diff --git a/components/cycle-day/symptoms/desire.js b/components/cycle-day/symptoms/desire.js index 6b690db..990b4f5 100644 --- a/components/cycle-day/symptoms/desire.js +++ b/components/cycle-day/symptoms/desire.js @@ -4,7 +4,6 @@ import { ScrollView } from 'react-native' import styles from '../../../styles' -import { saveSymptom } from '../../../db' import { intensity, desire } from '../../../i18n/en/cycle-day' import ActionButtonFooter from './action-button-footer' import SelectTabGroup from '../select-tab-group' @@ -13,15 +12,21 @@ import SymptomView from './symptom-view' export default class Desire extends SymptomView { constructor(props) { - super() + super(props) const cycleDay = props.cycleDay this.desire = cycleDay && cycleDay.desire const desireValue = this.desire && this.desire.value this.state = { currentValue: desireValue } } - save() { - saveSymptom('desire', this.props.date, { value: this.state.currentValue }) + symptomName = 'desire' + + onBackButtonPress() { + if (!this.state.currentValue) { + this.deleteSymptomEntry() + return + } + this.saveSymptomEntry({ value: this.state.currentValue }) } render() { diff --git a/components/cycle-day/symptoms/mood.js b/components/cycle-day/symptoms/mood.js index bbaa2e4..5221deb 100644 --- a/components/cycle-day/symptoms/mood.js +++ b/components/cycle-day/symptoms/mood.js @@ -4,7 +4,6 @@ import { TextInput, View } from 'react-native' -import { saveSymptom } from '../../../db' import { mood as labels } from '../../../i18n/en/cycle-day' import ActionButtonFooter from './action-button-footer' import SelectBoxGroup from '../select-box-group' @@ -14,7 +13,7 @@ import SymptomView from './symptom-view' export default class Mood extends SymptomView { constructor(props) { - super() + super(props) const cycleDay = props.cycleDay if (cycleDay && cycleDay.mood) { this.state = Object.assign({}, cycleDay.mood) @@ -26,12 +25,19 @@ export default class Mood extends SymptomView { } } - save() { + symptomName = "mood" + + onBackButtonPress() { + const nothingEntered = Object.values(this.state).every(val => !val) + if (nothingEntered) { + this.deleteSymptomEntry() + return + } const copyOfState = Object.assign({}, this.state) if (!copyOfState.other) { copyOfState.note = null } - saveSymptom('mood', this.props.date, copyOfState) + this.saveSymptomEntry(copyOfState) } toggleState = (key) => { diff --git a/components/cycle-day/symptoms/mucus.js b/components/cycle-day/symptoms/mucus.js index 16e5529..0eee93f 100644 --- a/components/cycle-day/symptoms/mucus.js +++ b/components/cycle-day/symptoms/mucus.js @@ -5,7 +5,6 @@ import { ScrollView } from 'react-native' import styles from '../../../styles' -import { saveSymptom } from '../../../db' import { mucus as labels } from '../../../i18n/en/cycle-day' import computeNfpValue from '../../../lib/nfp-mucus' import ActionButtonFooter from './action-button-footer' @@ -15,16 +14,24 @@ import SymptomView from './symptom-view' export default class Mucus extends SymptomView { constructor(props) { - super() + super(props) const cycleDay = props.cycleDay this.mucus = cycleDay && cycleDay.mucus this.state = this.mucus ? this.mucus : {} } - save() { + symptomName = 'mucus' + + onBackButtonPress() { + const nothingEntered = ['feeling', 'texture'].every(val => typeof this.state[val] != 'number') + if (nothingEntered) { + this.deleteSymptomEntry() + return + } + const feeling = this.state.feeling const texture = this.state.texture - saveSymptom('mucus', this.props.date, { + this.saveSymptomEntry({ feeling, texture, value: computeNfpValue(feeling, texture), diff --git a/components/cycle-day/symptoms/note.js b/components/cycle-day/symptoms/note.js index 06ee83a..08fac70 100644 --- a/components/cycle-day/symptoms/note.js +++ b/components/cycle-day/symptoms/note.js @@ -24,8 +24,14 @@ export default class Note extends SymptomView { } } - save() { - saveSymptom('note', this.props.date, { + symptomName = 'note' + + onBackButtonPress() { + if (!this.state.currentValue) { + this.deleteSymptomEntry() + return + } + this.saveSymptomEntry({ value: this.state.currentValue }) } diff --git a/components/cycle-day/symptoms/pain.js b/components/cycle-day/symptoms/pain.js index 48eb15b..aa1c074 100644 --- a/components/cycle-day/symptoms/pain.js +++ b/components/cycle-day/symptoms/pain.js @@ -27,12 +27,20 @@ export default class Pain extends SymptomView { } } - save() { + symptomName = 'pain' + + onBackButtonPress() { + const nothingEntered = Object.values(this.state).every(val => !val) + if (nothingEntered) { + this.deleteSymptomEntry() + return + } + const copyOfState = Object.assign({}, this.state) if (!copyOfState.other) { copyOfState.note = null } - saveSymptom('pain', this.props.date, copyOfState) + this.saveSymptomEntry(copyOfState) } toggleState = (key) => { diff --git a/components/cycle-day/symptoms/sex.js b/components/cycle-day/symptoms/sex.js index 4d5c8e6..596e3c6 100644 --- a/components/cycle-day/symptoms/sex.js +++ b/components/cycle-day/symptoms/sex.js @@ -5,7 +5,6 @@ import { ScrollView } from 'react-native' import styles from '../../../styles' -import { saveSymptom } from '../../../db' import { sex as sexLabels, contraceptives as contraceptivesLabels } from '../../../i18n/en/cycle-day' import { shared as sharedLabels } from '../../../i18n/en/labels' import ActionButtonFooter from './action-button-footer' @@ -27,12 +26,20 @@ export default class Sex extends SymptomView { if (this.state.note) this.state.other = true } - save() { + symptomName = "sex" + + onBackButtonPress() { + const nothingEntered = Object.values(this.state).every(val => !val) + if (nothingEntered) { + this.deleteSymptomEntry() + return + } + const copyOfState = Object.assign({}, this.state) if (!copyOfState.other) { copyOfState.note = null } - saveSymptom('sex', this.props.date, copyOfState) + this.saveSymptomEntry(copyOfState) } toggleState = (key) => { diff --git a/components/cycle-day/symptoms/symptom-view.js b/components/cycle-day/symptoms/symptom-view.js index 4110d99..987a993 100644 --- a/components/cycle-day/symptoms/symptom-view.js +++ b/components/cycle-day/symptoms/symptom-view.js @@ -1,10 +1,21 @@ import { Component } from 'react' import { BackHandler } from 'react-native' +import { saveSymptom } from '../../../db' export default class SymptomView extends Component { - constructor() { + constructor(props) { super() - this.backHandler = BackHandler.addEventListener('hardwareBackPress', this.save.bind(this)) + this.backHandler = BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPress.bind(this)) + this.symptomName = props.symptomName + this.date = props.date + } + + saveSymptomEntry(entry) { + saveSymptom(this.symptomName, this.date, entry) + } + + deleteSymptomEntry() { + saveSymptom(this.symptomName, this.date) } componentWillUnmount() { diff --git a/components/cycle-day/symptoms/temperature.js b/components/cycle-day/symptoms/temperature.js index f9de279..476d90c 100644 --- a/components/cycle-day/symptoms/temperature.js +++ b/components/cycle-day/symptoms/temperature.js @@ -9,7 +9,7 @@ import { import DateTimePicker from 'react-native-modal-datetime-picker-nevo' import padWithZeros from '../../helpers/pad-time-with-zeros' -import { getPreviousTemperature, saveSymptom } from '../../../db' +import { getPreviousTemperature } from '../../../db' import styles from '../../../styles' import { LocalTime, ChronoUnit } from 'js-joda' import { temperature as labels } from '../../../i18n/en/cycle-day' @@ -54,7 +54,14 @@ export default class Temp extends SymptomView { } } - save() { + symptomName = 'temperature' + + onBackButtonPress() { + if (this.state.temperature === '') { + this.deleteSymptomEntry() + return + } + this.checkRangeAndSave() } @@ -65,8 +72,8 @@ export default class Temp extends SymptomView { time: this.state.time, note: this.state.note } - saveSymptom('temperature', this.props.date, dataToSave) - this.props.navigate('CycleDay', {date: this.props.date}) + + this.saveSymptomEntry(dataToSave) } checkRangeAndSave = () => { From bc13f5c1e66d0bd64feff5e28894d050e233c8df Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Sun, 12 May 2019 13:18:03 +0200 Subject: [PATCH 11/17] Remove action button footer from symptom views --- components/cycle-day/symptoms/bleeding.js | 7 ------- components/cycle-day/symptoms/cervix.js | 8 ------- components/cycle-day/symptoms/desire.js | 10 +-------- components/cycle-day/symptoms/mood.js | 8 ------- components/cycle-day/symptoms/mucus.js | 7 ------- components/cycle-day/symptoms/note.js | 9 -------- components/cycle-day/symptoms/pain.js | 9 -------- components/cycle-day/symptoms/sex.js | 8 ------- components/cycle-day/symptoms/temperature.js | 22 -------------------- 9 files changed, 1 insertion(+), 87 deletions(-) diff --git a/components/cycle-day/symptoms/bleeding.js b/components/cycle-day/symptoms/bleeding.js index ddb5795..6b9c39c 100644 --- a/components/cycle-day/symptoms/bleeding.js +++ b/components/cycle-day/symptoms/bleeding.js @@ -6,7 +6,6 @@ import { } from 'react-native' import styles from '../../../styles' import { bleeding } from '../../../i18n/en/cycle-day' -import ActionButtonFooter from './action-button-footer' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' import SymptomView from './symptom-view' @@ -68,12 +67,6 @@ export default class Bleeding extends SymptomView { /> - ) } diff --git a/components/cycle-day/symptoms/cervix.js b/components/cycle-day/symptoms/cervix.js index 8ff4385..285d7de 100644 --- a/components/cycle-day/symptoms/cervix.js +++ b/components/cycle-day/symptoms/cervix.js @@ -5,9 +5,7 @@ import { ScrollView } from 'react-native' import styles from '../../../styles' -import { saveSymptom } from '../../../db' import { cervix as labels } from '../../../i18n/en/cycle-day' -import ActionButtonFooter from './action-button-footer' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' import SymptomView from './symptom-view' @@ -99,12 +97,6 @@ export default class Cervix extends SymptomView { /> - ) } diff --git a/components/cycle-day/symptoms/desire.js b/components/cycle-day/symptoms/desire.js index 990b4f5..9e9636b 100644 --- a/components/cycle-day/symptoms/desire.js +++ b/components/cycle-day/symptoms/desire.js @@ -5,7 +5,6 @@ import { } from 'react-native' import styles from '../../../styles' import { intensity, desire } from '../../../i18n/en/cycle-day' -import ActionButtonFooter from './action-button-footer' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' import SymptomView from './symptom-view' @@ -22,7 +21,7 @@ export default class Desire extends SymptomView { symptomName = 'desire' onBackButtonPress() { - if (!this.state.currentValue) { + if (typeof this.state.currentValue != 'number') { this.deleteSymptomEntry() return } @@ -49,13 +48,6 @@ export default class Desire extends SymptomView { /> - ) } diff --git a/components/cycle-day/symptoms/mood.js b/components/cycle-day/symptoms/mood.js index 5221deb..654d2e7 100644 --- a/components/cycle-day/symptoms/mood.js +++ b/components/cycle-day/symptoms/mood.js @@ -5,7 +5,6 @@ import { View } from 'react-native' import { mood as labels } from '../../../i18n/en/cycle-day' -import ActionButtonFooter from './action-button-footer' import SelectBoxGroup from '../select-box-group' import SymptomSection from './symptom-section' import styles from '../../../styles' @@ -73,13 +72,6 @@ export default class Mood extends SymptomView { } - !value)} - navigate={this.props.navigate} - /> ) } diff --git a/components/cycle-day/symptoms/mucus.js b/components/cycle-day/symptoms/mucus.js index 0eee93f..0c33ef8 100644 --- a/components/cycle-day/symptoms/mucus.js +++ b/components/cycle-day/symptoms/mucus.js @@ -7,7 +7,6 @@ import { import styles from '../../../styles' import { mucus as labels } from '../../../i18n/en/cycle-day' import computeNfpValue from '../../../lib/nfp-mucus' -import ActionButtonFooter from './action-button-footer' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' import SymptomView from './symptom-view' @@ -88,12 +87,6 @@ export default class Mucus extends SymptomView { /> - ) } diff --git a/components/cycle-day/symptoms/note.js b/components/cycle-day/symptoms/note.js index 08fac70..bf435db 100644 --- a/components/cycle-day/symptoms/note.js +++ b/components/cycle-day/symptoms/note.js @@ -6,8 +6,6 @@ import { } from 'react-native' import styles from '../../../styles' -import { saveSymptom } from '../../../db' -import ActionButtonFooter from './action-button-footer' import SymptomSection from './symptom-section' import { noteExplainer } from '../../../i18n/en/cycle-day' import { shared as sharedLabels } from '../../../i18n/en/labels' @@ -54,13 +52,6 @@ export default class Note extends SymptomView { /> - ) } diff --git a/components/cycle-day/symptoms/pain.js b/components/cycle-day/symptoms/pain.js index aa1c074..4a07ee5 100644 --- a/components/cycle-day/symptoms/pain.js +++ b/components/cycle-day/symptoms/pain.js @@ -4,10 +4,8 @@ import { TextInput, View } from 'react-native' -import { saveSymptom } from '../../../db' import { pain as labels } from '../../../i18n/en/cycle-day' import { shared as sharedLabels } from '../../../i18n/en/labels' -import ActionButtonFooter from './action-button-footer' import SelectBoxGroup from '../select-box-group' import SymptomSection from './symptom-section' import styles from '../../../styles' @@ -76,13 +74,6 @@ export default class Pain extends SymptomView { } - !value)} - navigate={this.props.navigate} - /> ) } diff --git a/components/cycle-day/symptoms/sex.js b/components/cycle-day/symptoms/sex.js index 596e3c6..8972fa3 100644 --- a/components/cycle-day/symptoms/sex.js +++ b/components/cycle-day/symptoms/sex.js @@ -7,7 +7,6 @@ import { import styles from '../../../styles' import { sex as sexLabels, contraceptives as contraceptivesLabels } from '../../../i18n/en/cycle-day' import { shared as sharedLabels } from '../../../i18n/en/labels' -import ActionButtonFooter from './action-button-footer' import SelectBoxGroup from '../select-box-group' import SymptomSection from './symptom-section' import SymptomView from './symptom-view' @@ -87,13 +86,6 @@ export default class Sex extends SymptomView { /> } - !value)} - navigate={this.props.navigate} - /> ) } diff --git a/components/cycle-day/symptoms/temperature.js b/components/cycle-day/symptoms/temperature.js index 476d90c..ce06a3c 100644 --- a/components/cycle-day/symptoms/temperature.js +++ b/components/cycle-day/symptoms/temperature.js @@ -15,7 +15,6 @@ import { LocalTime, ChronoUnit } from 'js-joda' import { temperature as labels } from '../../../i18n/en/cycle-day' import { scaleObservable } from '../../../local-storage' import { shared as sharedLabels } from '../../../i18n/en/labels' -import ActionButtonFooter from './action-button-footer' import config from '../../../config' import AppTextInput from '../../app-text-input' import AppText from '../../app-text' @@ -190,28 +189,7 @@ export default class Temp extends SymptomView { /> - ) } } - -function isInvalidTime(timeString) { - try { - LocalTime.parse(timeString) - } catch (err) { - return true - } - return false -} \ No newline at end of file From d1e16abe343c4650edb7086ea295a734bf002761 Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Sun, 12 May 2019 20:41:13 +0200 Subject: [PATCH 12/17] Make header back arrow function for auto save --- components/app.js | 17 +--- components/cycle-day/symptoms/bleeding.js | 53 +++++------ components/cycle-day/symptoms/cervix.js | 93 +++++++++---------- components/cycle-day/symptoms/desire.js | 28 +++--- components/cycle-day/symptoms/mood.js | 30 +++--- components/cycle-day/symptoms/mucus.js | 72 +++++++------- components/cycle-day/symptoms/note.js | 34 ++++--- components/cycle-day/symptoms/pain.js | 32 +++---- components/cycle-day/symptoms/sex.js | 53 +++++------ components/cycle-day/symptoms/symptom-view.js | 22 ++++- components/cycle-day/symptoms/temperature.js | 4 +- components/header/index.js | 7 +- components/header/symptom-view.js | 6 +- i18n/en/labels.js | 18 ++-- 14 files changed, 228 insertions(+), 241 deletions(-) diff --git a/components/app.js b/components/app.js index 178214c..fd9b61b 100644 --- a/components/app.js +++ b/components/app.js @@ -125,19 +125,12 @@ export default class App extends Component { goBack={this.handleBackButtonPress} /> } - {this.isSymptomView() && -
this.navigate(INFO_SYMPTOM_PAGE, { - symptomView: currentPage, - ...currentProps - })} - />} - + {!this.isSymptomView() && diff --git a/components/cycle-day/symptoms/bleeding.js b/components/cycle-day/symptoms/bleeding.js index 6b9c39c..9d94a03 100644 --- a/components/cycle-day/symptoms/bleeding.js +++ b/components/cycle-day/symptoms/bleeding.js @@ -1,6 +1,5 @@ import React from 'react' import { - View, Switch, ScrollView } from 'react-native' @@ -34,7 +33,7 @@ export default class Bleeding extends SymptomView { }) } - render() { + renderContent() { const bleedingRadioProps = [ { label: bleeding.labels[0], value: 0 }, { label: bleeding.labels[1], value: 1 }, @@ -42,32 +41,30 @@ export default class Bleeding extends SymptomView { { label: bleeding.labels[3], value: 3 }, ] return ( - - - - this.setState({ currentValue: val })} - /> - - - { - this.setState({ exclude: val }) - }} - value={this.state.exclude} - /> - - - + + + this.setState({ currentValue: val })} + /> + + + { + this.setState({ exclude: val }) + }} + value={this.state.exclude} + /> + + ) } } \ No newline at end of file diff --git a/components/cycle-day/symptoms/cervix.js b/components/cycle-day/symptoms/cervix.js index 285d7de..3feac91 100644 --- a/components/cycle-day/symptoms/cervix.js +++ b/components/cycle-day/symptoms/cervix.js @@ -1,6 +1,5 @@ import React from 'react' import { - View, Switch, ScrollView } from 'react-native' @@ -35,7 +34,7 @@ export default class Cervix extends SymptomView { }) } - render() { + renderContent() { const cervixOpeningRadioProps = [ { label: labels.opening.categories[0], value: 0 }, { label: labels.opening.categories[1], value: 1 }, @@ -52,52 +51,50 @@ export default class Cervix extends SymptomView { ] const mandatoryNotCompleted = typeof this.state.opening != 'number' || typeof this.state.firmness != 'number' return ( - - - - this.setState({ opening: val })} - /> - - - this.setState({ firmness: val })} - /> - - - this.setState({ position: val })} - /> - - - { - this.setState({ exclude: val }) - }} - value={this.state.exclude} - /> - - - + + + this.setState({ opening: val })} + /> + + + this.setState({ firmness: val })} + /> + + + this.setState({ position: val })} + /> + + + { + this.setState({ exclude: val }) + }} + value={this.state.exclude} + /> + + ) } } diff --git a/components/cycle-day/symptoms/desire.js b/components/cycle-day/symptoms/desire.js index 9e9636b..a619caf 100644 --- a/components/cycle-day/symptoms/desire.js +++ b/components/cycle-day/symptoms/desire.js @@ -28,27 +28,25 @@ export default class Desire extends SymptomView { this.saveSymptomEntry({ value: this.state.currentValue }) } - render() { + renderContent() { const desireRadioProps = [ { label: intensity[0], value: 0 }, { label: intensity[1], value: 1 }, { label: intensity[2], value: 2 } ] return ( - - - - this.setState({ currentValue: val })} - /> - - - + + + this.setState({ currentValue: val })} + /> + + ) } } diff --git a/components/cycle-day/symptoms/mood.js b/components/cycle-day/symptoms/mood.js index 654d2e7..a2b0a6a 100644 --- a/components/cycle-day/symptoms/mood.js +++ b/components/cycle-day/symptoms/mood.js @@ -47,19 +47,18 @@ export default class Mood extends SymptomView { } } - render() { + renderContent() { return ( - - - - - { this.state.other && + + + + { this.state.other && - } - - - + } + + ) } } diff --git a/components/cycle-day/symptoms/mucus.js b/components/cycle-day/symptoms/mucus.js index 0c33ef8..05aa1a1 100644 --- a/components/cycle-day/symptoms/mucus.js +++ b/components/cycle-day/symptoms/mucus.js @@ -38,7 +38,7 @@ export default class Mucus extends SymptomView { }) } - render() { + renderContent() { const mucusFeeling = [ { label: labels.feeling.categories[0], value: 0 }, { label: labels.feeling.categories[1], value: 1 }, @@ -52,42 +52,40 @@ export default class Mucus extends SymptomView { ] const mandatoryNotCompletedYet = typeof this.state.feeling != 'number' || typeof this.state.texture != 'number' return ( - - - - this.setState({ feeling: val })} - active={this.state.feeling} - /> - - - this.setState({ texture: val })} - active={this.state.texture} - /> - - - { - this.setState({ exclude: val }) - }} - value={this.state.exclude} - /> - - - + + + this.setState({ feeling: val })} + active={this.state.feeling} + /> + + + this.setState({ texture: val })} + active={this.state.texture} + /> + + + { + this.setState({ exclude: val }) + }} + value={this.state.exclude} + /> + + ) } } diff --git a/components/cycle-day/symptoms/note.js b/components/cycle-day/symptoms/note.js index bf435db..8cb8b75 100644 --- a/components/cycle-day/symptoms/note.js +++ b/components/cycle-day/symptoms/note.js @@ -34,25 +34,23 @@ export default class Note extends SymptomView { }) } - render() { + renderContent() { return ( - - - - { - this.setState({ currentValue: val }) - }} - value={this.state.currentValue} - /> - - - + + + { + this.setState({ currentValue: val }) + }} + value={this.state.currentValue} + /> + + ) } } diff --git a/components/cycle-day/symptoms/pain.js b/components/cycle-day/symptoms/pain.js index 4a07ee5..30ac355 100644 --- a/components/cycle-day/symptoms/pain.js +++ b/components/cycle-day/symptoms/pain.js @@ -2,7 +2,6 @@ import React from 'react' import { ScrollView, TextInput, - View } from 'react-native' import { pain as labels } from '../../../i18n/en/cycle-day' import { shared as sharedLabels } from '../../../i18n/en/labels' @@ -49,19 +48,18 @@ export default class Pain extends SymptomView { } } - render() { + renderContent() { return ( - - - - - { this.state.other && + + + + { this.state.other && - } - - - - ) + } + + ) } } diff --git a/components/cycle-day/symptoms/sex.js b/components/cycle-day/symptoms/sex.js index 8972fa3..9b195da 100644 --- a/components/cycle-day/symptoms/sex.js +++ b/components/cycle-day/symptoms/sex.js @@ -1,7 +1,6 @@ import React from 'react' import { TextInput, - View, ScrollView } from 'react-native' import styles from '../../../styles' @@ -49,32 +48,31 @@ export default class Sex extends SymptomView { } } - render() { + renderContent() { return ( - - - - - - - - + + + + + + + - {this.state.other && + {this.state.other && - } - - + } + ) } } diff --git a/components/cycle-day/symptoms/symptom-view.js b/components/cycle-day/symptoms/symptom-view.js index 987a993..9997f0c 100644 --- a/components/cycle-day/symptoms/symptom-view.js +++ b/components/cycle-day/symptoms/symptom-view.js @@ -1,11 +1,15 @@ +import React from 'react' import { Component } from 'react' -import { BackHandler } from 'react-native' +import { BackHandler, View } from 'react-native' import { saveSymptom } from '../../../db' +import Header from '../../header/symptom-view' +import { headerTitles } from '../../../i18n/en/labels' export default class SymptomView extends Component { constructor(props) { super() this.backHandler = BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPress.bind(this)) + this.globalBackhandler = props.handleBackButtonPress this.symptomName = props.symptomName this.date = props.date } @@ -21,4 +25,20 @@ export default class SymptomView extends Component { componentWillUnmount() { this.backHandler.remove() } + + render() { + return ( + +
{ + this.onBackButtonPress() + this.globalBackhandler() + }} + /> + {this.renderContent()} + + ) + } } \ No newline at end of file diff --git a/components/cycle-day/symptoms/temperature.js b/components/cycle-day/symptoms/temperature.js index ce06a3c..4e54eb8 100644 --- a/components/cycle-day/symptoms/temperature.js +++ b/components/cycle-day/symptoms/temperature.js @@ -116,13 +116,12 @@ export default class Temp extends SymptomView { this.setState({ isTimePickerVisible: true }) } - render() { + renderContent() { const inputStyle = [styles.temperatureTextInput] if (this.state.isSuggestion) { inputStyle.push(styles.temperatureTextInputSuggestion) } return ( - - ) } } diff --git a/components/header/index.js b/components/header/index.js index 9792d03..3de4034 100644 --- a/components/header/index.js +++ b/components/header/index.js @@ -3,7 +3,6 @@ import { Dimensions } from 'react-native' import CycleDayHeader from './cycle-day' import DefaultHeader from './default' import BackButtonHeader from './back-button' -import SymptomViewHeader from './symptom-view' export default function Header(p) { const middle = Dimensions.get('window').width / 2 @@ -11,11 +10,7 @@ export default function Header(p) { if (props.isCycleDayOverView) { return () - } - else if (props.isSymptomView) { - return () - } - else if (props.showBackButton) { + } else if (props.showBackButton) { return () } else { diff --git a/components/header/symptom-view.js b/components/header/symptom-view.js index 0b4e6d1..6f01113 100644 --- a/components/header/symptom-view.js +++ b/components/header/symptom-view.js @@ -2,7 +2,8 @@ import React from 'react' import { View, Text, - TouchableOpacity + TouchableOpacity, + Dimensions } from 'react-native' import styles, { iconStyles } from '../../styles' import FeatherIcon from 'react-native-vector-icons/Feather' @@ -10,11 +11,12 @@ import NavigationArrow from './navigation-arrow' import formatDate from '../helpers/format-date' export default function SymptomViewHeader(props) { + const middle = Dimensions.get('window').width / 2 return ( Date: Mon, 13 May 2019 08:12:46 +0200 Subject: [PATCH 13/17] Fix linter problems --- components/cycle-day/symptoms/cervix.js | 3 +- components/cycle-day/symptoms/desire.js | 1 - components/cycle-day/symptoms/mood.js | 4 +- components/cycle-day/symptoms/mucus.js | 4 +- components/cycle-day/symptoms/note.js | 1 - components/cycle-day/symptoms/symptom-view.js | 4 + components/cycle-day/symptoms/temperature.js | 124 +++++++++--------- components/header/symptom-view.js | 2 +- 8 files changed, 72 insertions(+), 71 deletions(-) diff --git a/components/cycle-day/symptoms/cervix.js b/components/cycle-day/symptoms/cervix.js index 3feac91..f58ebf2 100644 --- a/components/cycle-day/symptoms/cervix.js +++ b/components/cycle-day/symptoms/cervix.js @@ -49,7 +49,8 @@ export default class Cervix extends SymptomView { { label: labels.position.categories[1], value: 1 }, { label: labels.position.categories[2], value: 2 } ] - const mandatoryNotCompleted = typeof this.state.opening != 'number' || typeof this.state.firmness != 'number' + // TODO saving this info for notice when leaving incomplete data + // const mandatoryNotCompleted = typeof this.state.opening != 'number' || typeof this.state.firmness != 'number' return ( { + this.deleteSymptomEntry() + this.globalBackhandler() + }} /> {this.renderContent()} diff --git a/components/cycle-day/symptoms/temperature.js b/components/cycle-day/symptoms/temperature.js index 4e54eb8..c2e2575 100644 --- a/components/cycle-day/symptoms/temperature.js +++ b/components/cycle-day/symptoms/temperature.js @@ -122,72 +122,72 @@ export default class Temp extends SymptomView { inputStyle.push(styles.temperatureTextInputSuggestion) } return ( - - - - - °C - - - - - - { - this.setState({ - time: padWithZeros(jsDate), - isTimePickerVisible: false - }) - }} - onCancel={() => this.setState({ isTimePickerVisible: false })} - /> - - - + + + - - - { - this.setState({ exclude: val }) + °C + + + + + + { + this.setState({ + time: padWithZeros(jsDate), + isTimePickerVisible: false + }) }} - value={this.state.exclude} + onCancel={() => this.setState({ isTimePickerVisible: false })} /> - - + + + + + + + { + this.setState({ exclude: val }) + }} + value={this.state.exclude} + /> + + ) } } diff --git a/components/header/symptom-view.js b/components/header/symptom-view.js index 6f01113..6b6e384 100644 --- a/components/header/symptom-view.js +++ b/components/header/symptom-view.js @@ -31,7 +31,7 @@ export default function SymptomViewHeader(props) { props.goToSymptomInfo()} + onPress={props.deleteEntry} style={styles.infoButton} > Date: Mon, 13 May 2019 19:07:46 +0200 Subject: [PATCH 14/17] Don't crash on missing temperature value --- components/cycle-day/symptoms/temperature.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/cycle-day/symptoms/temperature.js b/components/cycle-day/symptoms/temperature.js index c2e2575..d053957 100644 --- a/components/cycle-day/symptoms/temperature.js +++ b/components/cycle-day/symptoms/temperature.js @@ -56,7 +56,7 @@ export default class Temp extends SymptomView { symptomName = 'temperature' onBackButtonPress() { - if (this.state.temperature === '') { + if (typeof this.state.temperature != 'string' || this.state.temperature === '') { this.deleteSymptomEntry() return } From 3715e0c4d28e5fbcadf9c247502e1e8d2ddc24fc Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Mon, 13 May 2019 20:30:25 +0200 Subject: [PATCH 15/17] Filter incomplete mucus values in sympto adapter --- lib/sympto-adapter.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/sympto-adapter.js b/lib/sympto-adapter.js index f2fb1c0..5caf8ea 100644 --- a/lib/sympto-adapter.js +++ b/lib/sympto-adapter.js @@ -113,6 +113,10 @@ function formatCycleForSympto(cycle) { if (hasIncompleteCervixValue(day)) { delete day.cervix } + // remove days with incomplete mucus value (because nfp-mucus returns null when that's the case) + if (day.mucus.value === null) { + delete day.mucus + } // change format ['bleeding', 'temperature', 'mucus'].forEach(symptomName => { if (day[symptomName]) day[symptomName] = day[symptomName].value From e781919434122be715176de3755c4193646b9674 Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Mon, 13 May 2019 20:34:13 +0200 Subject: [PATCH 16/17] Reset inadvertently changed file --- components/cycle-day/symptoms/info-symptom.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/cycle-day/symptoms/info-symptom.js b/components/cycle-day/symptoms/info-symptom.js index 2c75e88..951ed47 100644 --- a/components/cycle-day/symptoms/info-symptom.js +++ b/components/cycle-day/symptoms/info-symptom.js @@ -1,12 +1,11 @@ -import React from 'react' +import React, { Component } from 'react' import { ScrollView } from 'react-native' import AppText from '../../app-text' import labels from '../../../i18n/en/symptom-info.js' import FramedSegment from '../../framed-segment' import styles from '../../../styles/index' -import SymptomView from './symptom-view' -export default class InfoSymptom extends SymptomView { +export default class InfoSymptom extends Component { render() { const symptomView = this.props.symptomView const symptomMapping = { From 5057e1a38efc144c460241f51352eec669d82f5a Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Mon, 13 May 2019 20:41:57 +0200 Subject: [PATCH 17/17] Address MR change requests --- components/cycle-day/symptoms/symptom-view.js | 5 ++--- lib/sympto-adapter.js | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/components/cycle-day/symptoms/symptom-view.js b/components/cycle-day/symptoms/symptom-view.js index 7115826..6a805c8 100644 --- a/components/cycle-day/symptoms/symptom-view.js +++ b/components/cycle-day/symptoms/symptom-view.js @@ -1,5 +1,4 @@ -import React from 'react' -import { Component } from 'react' +import React, { Component } from 'react' import { BackHandler, View } from 'react-native' import { saveSymptom } from '../../../db' import Header from '../../header/symptom-view' @@ -8,9 +7,9 @@ import { headerTitles } from '../../../i18n/en/labels' export default class SymptomView extends Component { constructor(props) { super() + // every specific symptom view provides their own onBackButtonPress method this.backHandler = BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPress.bind(this)) this.globalBackhandler = props.handleBackButtonPress - this.symptomName = props.symptomName this.date = props.date } diff --git a/lib/sympto-adapter.js b/lib/sympto-adapter.js index 5caf8ea..efb6288 100644 --- a/lib/sympto-adapter.js +++ b/lib/sympto-adapter.js @@ -114,7 +114,7 @@ function formatCycleForSympto(cycle) { delete day.cervix } // remove days with incomplete mucus value (because nfp-mucus returns null when that's the case) - if (day.mucus.value === null) { + if (day.mucus && day.mucus.value === null) { delete day.mucus } // change format