Added cycle tracking beta to app
This commit is contained in:
parent
f12be22765
commit
178a7dfc2c
@ -169,6 +169,10 @@ i.green.icon.icon.icon.icon {
|
|||||||
}
|
}
|
||||||
.button {
|
.button {
|
||||||
box-shadow: 2px 2px 4px -2px rgba(40, 40, 40, 0.89) !important;
|
box-shadow: 2px 2px 4px -2px rgba(40, 40, 40, 0.89) !important;
|
||||||
|
transition: all 0.9s ease;
|
||||||
|
}
|
||||||
|
.button:hover {
|
||||||
|
box-shadow: 3px 2px 5px -2px rgba(40, 40, 40, 0.95) !important;
|
||||||
}
|
}
|
||||||
.ui.green.buttons, .ui.green.button, .ui.green.button:hover {
|
.ui.green.buttons, .ui.green.button, .ui.green.button:hover {
|
||||||
background-color: var(--main-accent);
|
background-color: var(--main-accent);
|
||||||
|
@ -1,101 +1,423 @@
|
|||||||
<style>
|
<style>
|
||||||
.calendar {
|
.squire-box {
|
||||||
width: 300px;
|
padding: 0 !important;
|
||||||
height: 400px;
|
}
|
||||||
display: inline-block;
|
div.calendar {
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
min-height: 350px;
|
||||||
|
display: flex;
|
||||||
|
margin: 5px 10px 15px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
.day {
|
.day {
|
||||||
width: 40px;
|
/*width: calc(100% / 8);*/
|
||||||
height: 40px;
|
flex: 0 0 calc(14.28% - 2px);
|
||||||
|
height: 50px;
|
||||||
border: 1px solid var(--border_color);
|
border: 1px solid var(--border_color);
|
||||||
display: inline-block;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
/*overflow: hidden;*/
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 1px;
|
||||||
|
padding: 0 0 0 5px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
.today {
|
.today {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
.day ~ .active {
|
.day ~ .active {
|
||||||
|
|
||||||
background-color: var(--main-accent);
|
|
||||||
color: var(--body_bg_color);
|
|
||||||
}
|
|
||||||
.day ~ .has-data {
|
|
||||||
outline: #07f4f4;
|
outline: #07f4f4;
|
||||||
outline-style: none;
|
outline-style: none;
|
||||||
outline-width: medium;
|
outline-width: medium;
|
||||||
outline-style: none;
|
outline-style: none;
|
||||||
outline-offset: -4px;
|
outline-offset: -1px;
|
||||||
outline-style: solid;
|
outline-style: solid;
|
||||||
outline-width: 2px;
|
outline-width: 3px;
|
||||||
}
|
}
|
||||||
|
.day ~ .has-data {
|
||||||
|
|
||||||
|
}
|
||||||
|
.day ~ .no-data {
|
||||||
|
background: #c7c7c787;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
.day > .number {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 5px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
.day > .sex {
|
||||||
|
font-size: 0.7em;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: rgba(249, 0, 0, 0.15);
|
||||||
|
color: white;
|
||||||
|
padding: 0 0 0 4px;
|
||||||
|
z-index: 10;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
height: 26px;
|
||||||
|
}
|
||||||
|
.day > .period {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 1px;
|
||||||
|
left: 1px;
|
||||||
|
right: 1px;
|
||||||
|
height: 5px;
|
||||||
|
background: red;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
.day > .mucus {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
min-height: 10px;
|
||||||
|
background: #abecff7d;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.day > .notes {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-holder {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
.key-display {
|
||||||
|
/*width: calc(100% - 70px);*/
|
||||||
|
float: left;
|
||||||
|
height: 50px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 10px 0 0 10px;
|
||||||
|
/*flex-basis: 70%;*/
|
||||||
|
flex: 1 0 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-buttons {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.option-buttons > div.button {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0 0 3px 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="squire-box">
|
<div class="squire-box">
|
||||||
|
|
||||||
<h3>Cycle Tracking Beta
|
|
||||||
|
<div class="ui centered dividing header">
|
||||||
|
<br>
|
||||||
|
Metric Tracking Beta
|
||||||
<span v-on:click="deleteData()">
|
<span v-on:click="deleteData()">
|
||||||
<i class="clickable trash icon"></i>
|
<i class="clickable trash icon"></i>
|
||||||
</span>
|
</span>
|
||||||
</h3>
|
</div>
|
||||||
|
|
||||||
|
<!-- data input -->
|
||||||
|
<div class="ui basic segment">
|
||||||
|
<div class="ui very compact grid">
|
||||||
|
<div class="ui twelve wide middle aligned column">
|
||||||
|
<div class="ui header">
|
||||||
|
Entry for {{ calendar.monthName }}, {{ calendar.today }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui four wide right aligned middle aligned column">
|
||||||
|
<span v-if="saving == 0">
|
||||||
|
<i class="heart icon"></i>
|
||||||
|
</span>
|
||||||
|
<span v-if="saving == 1">
|
||||||
|
<i class="asterisk icon"></i>
|
||||||
|
</span>
|
||||||
|
<span v-if="saving == 2">
|
||||||
|
<i class="sync loading icon"></i>
|
||||||
|
</span>
|
||||||
|
<span v-if="saving == 3">
|
||||||
|
<i class="green circle check icon"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ui form">
|
||||||
|
<div class="ui compact grid">
|
||||||
|
<div v-for="field in fields" :class="defaultFields[field].width || 'eight wide column'">
|
||||||
|
<!-- field label display -->
|
||||||
|
<div class="ui very compact grid">
|
||||||
|
<div class="ui fourteen wide column">
|
||||||
|
<i v-if="defaultFields[field].icon" :class="`${defaultFields[field].icon} icon`"></i>
|
||||||
|
<b>{{ defaultFields[field].label }} </b>
|
||||||
|
</div>
|
||||||
|
<div class="ui two wide right aligned column">
|
||||||
|
<span v-on:click="fieldRemove(field)">
|
||||||
|
<i class="grey clickable minus icon"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- float -->
|
||||||
|
<div v-if="defaultFields[field].type == 'float'" class="ui fluid input">
|
||||||
|
<input type="text" :placeholder="defaultFields[field].label" v-on:keyup="e => saveField(field, e.target.value)" :value="openDay[field]">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- range -->
|
||||||
|
<div v-if="defaultFields[field].type == 'shortRange'">
|
||||||
|
<div :class="{green:(openDay[field] == 1)}" v-on:click="saveField(field, 1)" class="ui button">1</div>
|
||||||
|
<div :class="{green:(openDay[field] == 2)}" v-on:click="saveField(field, 2)" class="ui button">2</div>
|
||||||
|
<div :class="{green:(openDay[field] == 3)}" v-on:click="saveField(field, 3)" class="ui button">3</div>
|
||||||
|
<div :class="{green:(openDay[field] == 4)}" v-on:click="saveField(field, 4)" class="ui button">4</div>
|
||||||
|
<div :class="{green:(openDay[field] == 5)}" v-on:click="saveField(field, 5)" class="ui button">5</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- text area -->
|
||||||
|
<div v-if="defaultFields[field].type == 'text'">
|
||||||
|
<textarea rows="3" v-on:keyup="e => saveField(field, e.target.value)">{{ openDay[field] }}</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- boolean -->
|
||||||
|
<div v-if="defaultFields[field].type == 'boolean'">
|
||||||
|
<div :class="{green:(openDay[field] == 1)}" v-on:click="saveField(field, 1)" class="ui button">Yes</div>
|
||||||
|
<div :class="{green:(openDay[field] == 2)}" v-on:click="saveField(field, 2)" class="ui button">No</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="['sex','period','mucus','pms'].includes(defaultFields[field].type)">
|
||||||
|
<div class="option-buttons">
|
||||||
|
<div :class="{green:(openDay[field] == key)}" v-on:click="saveField(field, key)" class="ui compact button" v-for="(item,key) in fieldTypes[defaultFields[field].type].split(',')">{{ item }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<span class="clickable" v-on:click="toggleFolded('fieldOptions')">
|
||||||
|
<i class="tiny circular blue clickable plus icon"></i>
|
||||||
|
Add/Remove Fields
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="ui very compact grid" v-if="folded.includes('fieldOptions')">
|
||||||
|
<div class="ui row">
|
||||||
|
<div class="eight wide column">
|
||||||
|
<span>
|
||||||
|
<i class="ui disabeld plus icon"></i>
|
||||||
|
</span>
|
||||||
|
<b>Name</b>
|
||||||
|
</div>
|
||||||
|
<div class="six wide column">
|
||||||
|
<b>Type</b>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui row" v-for="(field,fieldId) in defaultFields" v-if="!fields.includes(fieldId)">
|
||||||
|
<div class="eight wide column">
|
||||||
|
<span v-on:click="fieldAdd(fieldId)">
|
||||||
|
<i class="ui clickable orange plus icon"></i>
|
||||||
|
</span>
|
||||||
|
{{ field.label }}
|
||||||
|
</div>
|
||||||
|
<div class="six wide column">
|
||||||
|
{{ fieldTypes[field.type] }}
|
||||||
|
</div>
|
||||||
|
<div class="two wide column">
|
||||||
|
{{ openDay[fieldId] }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- day navigation -->
|
||||||
|
<div class="ui compact grid">
|
||||||
|
<div class="ui five wide right aligned column">
|
||||||
|
<div class="ui tiny basic compact button" v-on:click="openDayData(getPreviousDay)">
|
||||||
|
<i class="caret left icon"></i>
|
||||||
|
Previous
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui six wide center aligned column">
|
||||||
|
<div class="ui tiny basic compact button" v-on:click="openDayData(getToday)">
|
||||||
|
<i class="caret down icon"></i>
|
||||||
|
Today
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui five wide left aligned column">
|
||||||
|
<div class="ui tiny basic compact button" v-on:click="openDayData(getNextDay)">
|
||||||
|
Next
|
||||||
|
<i class="caret right icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ui very compact grid">
|
||||||
|
<div class="ui four wide column">
|
||||||
|
<span v-on:click="openDayData(getPreviousMonth)">
|
||||||
|
<i class="clickable caret square left outline icon"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="ui eight wide center aligned column">
|
||||||
|
<p>{{calendar.monthName}}, {{calendar.year}}</p>
|
||||||
|
</div>
|
||||||
|
<div class="ui four wide right aligned column">
|
||||||
|
<span v-on:click="openDayData(getNextMonth)">
|
||||||
|
<i class="clickable caret square right outline icon"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="calendar">
|
<div class="calendar">
|
||||||
<p>{{calendar.monthName}}, {{calendar.year}}</p>
|
|
||||||
<div v-for="day in calendar.weekdays" class="day">
|
<div v-for="day in calendar.weekdays" class="day">
|
||||||
{{ day }}
|
{{ day }}
|
||||||
</div>
|
</div>
|
||||||
<div v-for="day in calendar.days" class="day"
|
<div v-for="day in calendar.days" class="day"
|
||||||
:class="{
|
:class="{
|
||||||
'today':day == calendar.today,
|
'today':day == calendar.today,
|
||||||
'active':dateCode == `${day}.${calendar.month}.${calendar.year}`,
|
'active':calendar.dateCode == `${day}.${calendar.month}.${calendar.year}`,
|
||||||
'has-data':cycleData[`${day}.${calendar.month}.${calendar.year}`],
|
'has-data':cycleData[`${day}.${calendar.month}.${calendar.year}`],
|
||||||
|
'no-data':showDayDataColor(day),
|
||||||
}"
|
}"
|
||||||
v-on:click="openDayData(`${day}.${calendar.month}.${calendar.year}`)">
|
v-on:click="openDayData(`${day}.${calendar.month}.${calendar.year}`)">
|
||||||
{{ day }}
|
<span class="number">{{ day }}</span>
|
||||||
|
<!-- period display -->
|
||||||
|
<span v-if="isPeriod(day)" class="period"></span>
|
||||||
|
<!-- sex display -->
|
||||||
|
<span v-if="isSex(day) > 0" class="sex" >
|
||||||
|
<span v-if="isSex(day) == 1">
|
||||||
|
<i class="red heart icon"></i>
|
||||||
|
</span>
|
||||||
|
<span v-if="isSex(day) == 2">
|
||||||
|
<i class="red baby carriage icon"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<!-- mucus display -->
|
||||||
|
<span v-if="isMucus(day)" class="mucus" :style="`top:${100-(isMucus(day)*22)}%`">
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ui form">
|
<div class="ui basic segment">
|
||||||
<h3><input type="text" v-model="dateCode" v-on:keypress.enter="openDayData(dateCode)"></h3>
|
<div class="ui clickable" v-on:click="toggleFolded('key')">
|
||||||
<div class="field" v-for="field in fields">
|
<i class="tiny circular blue clickable plus icon"></i>
|
||||||
<label>{{ field.label }}</label>
|
Calendar Explanation
|
||||||
|
|
||||||
<div v-for="(value, key) in openDay">
|
|
||||||
|
|
||||||
<!-- float -->
|
|
||||||
<div v-if="field.type == 'float' && field.id == key" class="ui left icon input">
|
|
||||||
<input type="text" :placeholder="field.label" v-on:keyup="e => saveField(field.id, e.target.value)" :value="value">
|
|
||||||
<i class="thermometer half icon"></i>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="ui segment key-holder" v-if="folded.includes('key')">
|
||||||
<!-- range -->
|
<div class="day">
|
||||||
<div v-if="field.type == 'range' && field.id == key">
|
<span class="number">1</span>
|
||||||
<div :class="{green:(value == 1)}" v-on:click="saveField(field.id, 1)" class="ui button">1</div>
|
<span class="period"></span>
|
||||||
<div :class="{green:(value == 2)}" v-on:click="saveField(field.id, 2)" class="ui button">2</div>
|
|
||||||
<div :class="{green:(value == 3)}" v-on:click="saveField(field.id, 3)" class="ui button">3</div>
|
|
||||||
<div :class="{green:(value == 4)}" v-on:click="saveField(field.id, 4)" class="ui button">4</div>
|
|
||||||
<div :class="{green:(value == 5)}" v-on:click="saveField(field.id, 5)" class="ui button">5</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<span class="key-display">
|
||||||
|
Period in Progress
|
||||||
|
</span>
|
||||||
|
|
||||||
<!-- text area -->
|
<div class="day">
|
||||||
<div v-if="field.type == 'text' && field.id == key">
|
<span class="number">1</span>
|
||||||
<textarea rows="3" v-on:keyup="e => saveField(field.id, e.target.value)">
|
<span class="mucus" :style="`top:50%`">
|
||||||
{{ value }}
|
</span>
|
||||||
</textarea>
|
|
||||||
</div>
|
</div>
|
||||||
|
<span class="key-display">
|
||||||
|
Amount of cervical mucus
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="day">
|
||||||
|
<span class="number">1</span>
|
||||||
|
<span class="sex" >
|
||||||
|
<span>
|
||||||
|
<i class="red heart icon"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<span class="key-display">
|
||||||
|
Had sex with contraception
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="day">
|
||||||
|
<span class="number">1</span>
|
||||||
|
<span class="sex" >
|
||||||
|
<span>
|
||||||
|
<i class="red baby carriage icon"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<span class="key-display">
|
||||||
|
Had sex without contraception
|
||||||
|
</span>
|
||||||
|
|
||||||
<div class="ui green save button" v-on:click="saveDayData">
|
<div class="day no-data">
|
||||||
Save
|
<span class="number">1</span>
|
||||||
|
</div>
|
||||||
|
<span class="key-display">
|
||||||
|
No Data entered
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Temp graph -->
|
||||||
|
<div class="ui basic segment" >
|
||||||
|
<div class="ui dividing header">
|
||||||
|
Basil temp last {{ tempChartDays }} days
|
||||||
|
</div>
|
||||||
|
<div class="ui tiny compact basic fluid buttons">
|
||||||
|
<div :class="{'green':(tempChartDays == 1000000)}" v-on:click="tempChartDays = 1000000; graphCurrentData()" class="ui button">ALL</div>
|
||||||
|
<div :class="{'green':(tempChartDays == 360)}" v-on:click="tempChartDays = 360; graphCurrentData()" class="ui button">360</div>
|
||||||
|
<div :class="{'green':(tempChartDays == 180)}" v-on:click="tempChartDays = 180; graphCurrentData()" class="ui button">180</div>
|
||||||
|
<div :class="{'green':(tempChartDays == 90)}" v-on:click="tempChartDays = 90; graphCurrentData()" class="ui button">90</div>
|
||||||
|
<div :class="{'green':(tempChartDays == 60)}" v-on:click="tempChartDays = 60; graphCurrentData()" class="ui button">60</div>
|
||||||
|
<div :class="{'green':(tempChartDays == 30)}" v-on:click="tempChartDays = 30; graphCurrentData()" class="ui button">30</div>
|
||||||
|
<div :class="{'green':(tempChartDays == 7)}" v-on:click="tempChartDays = 7; graphCurrentData()" class="ui button">7</div>
|
||||||
|
</div>
|
||||||
|
<div id="graphdiv" style="width: 100%; min-height: 320px;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- notes -->
|
||||||
|
<div class="ui basic segment">
|
||||||
|
<div class="ui clickable" v-on:click="toggleFolded('notes')">
|
||||||
|
<i class="tiny circular blue clickable plus icon"></i>
|
||||||
|
Additional Notes
|
||||||
|
</div>
|
||||||
|
<div class="ui fitted segments" v-if="folded.includes('notes')">
|
||||||
|
<div class="ui segment">
|
||||||
|
<a href="https://www.plannedparenthood.org/learn/birth-control/fertility-awareness">Further Reading on planned parenthood.</a>
|
||||||
|
</div>
|
||||||
|
<div class="ui segment">
|
||||||
|
Follicular phase
|
||||||
|
Luteal phase
|
||||||
|
</div>
|
||||||
|
<div class="ui segment">
|
||||||
|
Ovulation is detected by sustained temperate elevation. <br>
|
||||||
|
Ovulation can only be determined in hindsight, as progesterone is what makes the temperatures rise, and progesterone is only produced in abundance post-ovulation.
|
||||||
|
</div>
|
||||||
|
<div class="ui segment">
|
||||||
|
Some people may find that their temperature drops the day before or the day their period arrives. This is a very helpful sign in knowing that your period is on it’s way!
|
||||||
|
</div>
|
||||||
|
<div class="ui segment">
|
||||||
|
About halfway through your menstrual cycle, your hormones tell one of your ovaries to release a mature egg — this is called ovulation. Most people don’t feel it when they ovulate, but some ovulation symptoms are bloating, spotting, or a little pain in your lower belly that you may only feel on one side.
|
||||||
|
</div>
|
||||||
|
<div class="ui segment">
|
||||||
|
If you do get pregnant, your body needs the lining — that’s why your period stops during pregnancy. Your period comes back when you’re not pregnant anymore.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- spacer at the bottom for mobile menu -->
|
||||||
|
<div class="ui basic segment"></div>
|
||||||
|
|
||||||
|
<!-- may or may not need digraph CSS, maybe disect -->
|
||||||
|
<!-- <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.min.css" /> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -103,24 +425,50 @@
|
|||||||
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
|
var BASAL_TEMP = 'BT'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CycleTracking',
|
name: 'MetricTracking',
|
||||||
components: {
|
components: {
|
||||||
'logo':require('@/components/LogoComponent.vue').default,
|
'logo':require('@/components/LogoComponent.vue').default,
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
appWorkingDate: null,
|
folded:[],
|
||||||
|
working: true,
|
||||||
|
showNotes: false,
|
||||||
fields:[],
|
fields:[],
|
||||||
defaultFields:[
|
fieldTypes:{
|
||||||
{'type':'float','label':'Basil Temp', 'id':'BT'},
|
'float':'Precise Number',
|
||||||
{'type':'range','label':'Cervical Mucus', 'id':'CM'},
|
'shortRange':'Options 1-5',
|
||||||
{'type':'text','label':'Notes', 'id':'NO'},
|
'longRange':'Options 1-10',
|
||||||
],
|
'text':'Text Input',
|
||||||
|
'boolean':'Yes, No',
|
||||||
|
'period':'No, 1. Light, 2. Normal, 3. Heavy, 4. Irregular, 5. Painful',
|
||||||
|
'mucus':'None, 1. Watery, 2. Eggwhite, 3. Creamy, 4. Sticky',
|
||||||
|
'sex':'None, With contraception, Without contraception',
|
||||||
|
'pms':'No, 1. Maybe, 2. A little, 3. Real Cranky',
|
||||||
|
},
|
||||||
|
defaultFields:{
|
||||||
|
'BT': {'type':'float','label':'Basal Temp','icon':'thermometer half','width':'sixteen wide column'},
|
||||||
|
'CM': {'type':'mucus','label':'Cervical Mucus','icon':'','width':'eight wide column'},
|
||||||
|
'PE': {'type':'period','label':'Having Period','icon':'','width':'eight wide column'},
|
||||||
|
'SE': {'type':'sex','label':'Sex','icon':'','width':'eight wide column'},
|
||||||
|
'NO': {'type':'text','label':'Notes','icon':'','width':'sixteen wide column'},
|
||||||
|
'OV': {'type':'boolean','label':'Suspect Ovulation','icon':'','width':''},
|
||||||
|
'PM': {'type':'pms','label':'PMS','icon':'','width':''},
|
||||||
|
'HO': {'type':'boolean','label':'Horny','icon':'','width':''},
|
||||||
|
'DI': {'type':'text','label':'Diet','icon':'','width':''},
|
||||||
|
'EX': {'type':'text','label':'Exercise','icon':'','width':''},
|
||||||
|
},
|
||||||
cycleData: {},
|
cycleData: {},
|
||||||
dateCode: null,
|
totalEntries: 0,
|
||||||
openDay: [],
|
openDay: {},
|
||||||
|
saveDataDebounce:null,
|
||||||
|
saving: 0, // 0 blank, 1 modified, 2 saving, 3 saved
|
||||||
calendar: {
|
calendar: {
|
||||||
|
dateObject: null,
|
||||||
|
dateCode: null,
|
||||||
monthName: '',
|
monthName: '',
|
||||||
month: '',
|
month: '',
|
||||||
year: '',
|
year: '',
|
||||||
@ -128,6 +476,7 @@
|
|||||||
weekdays: ['S','M','T','W','T','F','S'],
|
weekdays: ['S','M','T','W','T','F','S'],
|
||||||
today: 0,
|
today: 0,
|
||||||
},
|
},
|
||||||
|
tempChartDays: 60,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
@ -141,25 +490,178 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup date code
|
// set up reactive open day object
|
||||||
// day - month - year
|
Object.keys(this.defaultFields).forEach(fieldId => {
|
||||||
const now = new Date()
|
this.$set(this.openDay, fieldId, '')
|
||||||
this.appWorkingDate = now
|
})
|
||||||
const dateSetup = [
|
|
||||||
now.getDate(), // 1-31 (Day)
|
|
||||||
now.getMonth()+1, // 0-11 (Month)
|
|
||||||
now.getFullYear(), // 1888-2022 (Year)
|
|
||||||
]
|
|
||||||
|
|
||||||
this.dateCode = dateSetup.join('.')
|
// Include JS libraries
|
||||||
|
let graphs = document.createElement('script')
|
||||||
|
graphs.setAttribute('src', '//cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.min.js')
|
||||||
|
document.head.appendChild(graphs)
|
||||||
|
|
||||||
this.setupCalendar(this.appWorkingDate)
|
// setup date to today
|
||||||
|
this.setupCalendar()
|
||||||
|
|
||||||
this.fetchCycleData()
|
this.fetchCycleData()
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
getToday(){
|
||||||
|
return this.generateDateCode(new Date())
|
||||||
|
},
|
||||||
|
getPreviousDay(){
|
||||||
|
const workingDate = this.calendar.dateObject || new Date()
|
||||||
|
workingDate.setDate(workingDate.getDate()-1)
|
||||||
|
|
||||||
|
return this.generateDateCode(workingDate)
|
||||||
|
},
|
||||||
|
getNextDay(){
|
||||||
|
const workingDate = this.calendar.dateObject || new Date()
|
||||||
|
workingDate.setDate(workingDate.getDate()+1)
|
||||||
|
|
||||||
|
return this.generateDateCode(workingDate)
|
||||||
|
},
|
||||||
|
getNextMonth(){
|
||||||
|
const workingDate = this.calendar.dateObject || new Date()
|
||||||
|
workingDate.setMonth(workingDate.getMonth() +1)
|
||||||
|
|
||||||
|
return this.generateDateCode(workingDate)
|
||||||
|
},
|
||||||
|
getPreviousMonth(){
|
||||||
|
const workingDate = this.calendar.dateObject || new Date()
|
||||||
|
workingDate.setMonth(workingDate.getMonth() -1)
|
||||||
|
|
||||||
|
return this.generateDateCode(workingDate)
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
toggleFolded(key){
|
||||||
|
const index = this.folded.indexOf(key)
|
||||||
|
if(index == -1){
|
||||||
|
this.folded.push(key)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.folded.splice(index,1)
|
||||||
|
},
|
||||||
|
showDayDataColor(day){
|
||||||
|
// Determine if day has any data set
|
||||||
|
if(day == ''){
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return !(this.cycleData[`${day}.${this.calendar.month}.${this.calendar.year}`])
|
||||||
|
},
|
||||||
|
isPeriod(day){
|
||||||
|
const data = this.cycleData[`${day}.${this.calendar.month}.${this.calendar.year}`]
|
||||||
|
if(data?.PE > 0){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isSex(day){
|
||||||
|
const data = this.cycleData[`${day}.${this.calendar.month}.${this.calendar.year}`]
|
||||||
|
return data?.SE
|
||||||
|
},
|
||||||
|
isMucus(day){
|
||||||
|
const data = this.cycleData[`${day}.${this.calendar.month}.${this.calendar.year}`]
|
||||||
|
return data?.CM
|
||||||
|
},
|
||||||
|
isNotes(day){
|
||||||
|
const data = this.cycleData[`${day}.${this.calendar.month}.${this.calendar.year}`]
|
||||||
|
return data?.NO
|
||||||
|
},
|
||||||
|
isTemp(day){
|
||||||
|
const data = this.cycleData[`${day}.${this.calendar.month}.${this.calendar.year}`]
|
||||||
|
return data?.BT
|
||||||
|
},
|
||||||
|
fieldRemove(field){
|
||||||
|
for (let i = this.fields.length - 1; i >= 0; i--) {
|
||||||
|
if(field == this.fields[i]){
|
||||||
|
this.fields.splice(i,1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.saveCycleData()
|
||||||
|
},
|
||||||
|
fieldAdd(fieldId){
|
||||||
|
this.fields.push(fieldId)
|
||||||
|
this.saveCycleData()
|
||||||
|
},
|
||||||
|
graphCurrentData(){
|
||||||
|
|
||||||
|
// CSV or path to a CSV file.
|
||||||
|
let dataString = "Date,Temperature,Average\n"
|
||||||
|
|
||||||
|
// Excel date format YYYYMMDD
|
||||||
|
const convertToExcelDate = (dateCode) => {
|
||||||
|
return dateCode
|
||||||
|
.split('.')
|
||||||
|
.reverse()
|
||||||
|
.map(item => String(item).padStart(2,0))
|
||||||
|
.join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataKeys = Object.keys(this.cycleData)
|
||||||
|
|
||||||
|
// calculate average
|
||||||
|
let average = 0.0
|
||||||
|
let totalTemps = 0
|
||||||
|
for (var i = 0; i < dataKeys.length; i++) {
|
||||||
|
const current = this.cycleData[dataKeys[i]]
|
||||||
|
if(current.BT){
|
||||||
|
average += parseFloat(current.BT)
|
||||||
|
totalTemps++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
average = (average/totalTemps)
|
||||||
|
|
||||||
|
// build CSV data
|
||||||
|
for (var i = 0; i < dataKeys.length; i++) {
|
||||||
|
const current = this.cycleData[dataKeys[i]]
|
||||||
|
let nextFragment = []
|
||||||
|
|
||||||
|
// push date code
|
||||||
|
nextFragment.push(convertToExcelDate(dataKeys[i]))
|
||||||
|
|
||||||
|
if(current.BT){
|
||||||
|
// parse temp to fixed length float 00.00
|
||||||
|
nextFragment.push(parseFloat(current.BT).toFixed(2))
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
nextFragment.push(average)
|
||||||
|
|
||||||
|
dataString += nextFragment.join(',') + "\n"
|
||||||
|
|
||||||
|
if(i >= this.tempChartDays){
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let graphDiv = document.getElementById("graphdiv")
|
||||||
|
const graphOptions = {
|
||||||
|
animatedZoom: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
const g = new Dygraph(graphDiv, dataString ,graphOptions)
|
||||||
|
},
|
||||||
saveField(fieldId, value){
|
saveField(fieldId, value){
|
||||||
this.openDay[fieldId] = value
|
|
||||||
|
// Dont save value if it hasn't changed
|
||||||
|
if(this.openDay[fieldId] == value){ return }
|
||||||
|
|
||||||
|
// update field to be reactive
|
||||||
|
this.$set(this.openDay, fieldId, value)
|
||||||
|
|
||||||
|
// remove debounce and set to modified
|
||||||
|
this.$nextTick(() => {
|
||||||
|
//0 blank, 1 modified, 2 saving, 3 saved
|
||||||
|
this.saving = 1
|
||||||
|
clearTimeout(this.saveDataDebounce)
|
||||||
|
this.saveDataDebounce = setTimeout(() => {
|
||||||
|
this.saveDayData()
|
||||||
|
}, 500)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
openDayData(dateCode){
|
openDayData(dateCode){
|
||||||
|
|
||||||
@ -168,16 +670,14 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dateCode = dateCode || this.dateCode
|
this.setupCalendar(this.dateCodeToDate(dateCode))
|
||||||
|
|
||||||
let currentDay = this.cycleData[this.dateCode] || {}
|
// open day has all fields defined, just set values
|
||||||
|
let currentDay = this.cycleData[dateCode] || {}
|
||||||
//Set up each entry empty or with current value
|
Object.keys(this.openDay).forEach(fieldId => {
|
||||||
this.fields.forEach(field => {
|
this.openDay[fieldId] = currentDay[fieldId] || ''
|
||||||
currentDay[field.id] = currentDay[field.id] || ''
|
|
||||||
})
|
})
|
||||||
|
|
||||||
this.openDay = currentDay
|
|
||||||
|
|
||||||
},
|
},
|
||||||
saveDayData(){
|
saveDayData(){
|
||||||
@ -185,15 +685,18 @@
|
|||||||
// remove empty keys
|
// remove empty keys
|
||||||
let cleanDayData = {}
|
let cleanDayData = {}
|
||||||
Object.keys(this.openDay).forEach(key => {
|
Object.keys(this.openDay).forEach(key => {
|
||||||
if(this.openDay[key] != ''){
|
if(this.openDay[key] != '' && this.openDay[key] != 0){
|
||||||
cleanDayData[key] = this.openDay[key]
|
cleanDayData[key] = this.openDay[key]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.cycleData[this.dateCode] = cleanDayData
|
// Only save entry if there is data
|
||||||
|
delete this.cycleData[this.calendar.dateCode]
|
||||||
|
if(Object.keys(cleanDayData).length > 0){
|
||||||
|
this.cycleData[this.calendar.dateCode] = cleanDayData
|
||||||
|
}
|
||||||
|
|
||||||
// Update calendar
|
this.graphCurrentData()
|
||||||
this.setupCalendar(this.appWorkingDate)
|
|
||||||
|
|
||||||
this.saveCycleData()
|
this.saveCycleData()
|
||||||
|
|
||||||
@ -211,14 +714,20 @@
|
|||||||
console.log('Didnt parse json')
|
console.log('Didnt parse json')
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(appData)
|
// console.clear()
|
||||||
|
// console.log(appData)
|
||||||
|
|
||||||
this.cycleData = appData?.cycleData || {}
|
this.cycleData = appData?.cycleData || {}
|
||||||
this.fields = appData?.fields || []
|
this.fields = appData?.fields || []
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
this.totalEntries = Object.keys(this.cycleData).length
|
||||||
this.setupFields()
|
this.setupFields()
|
||||||
this.openDayData(this.dateCode)
|
this.openDayData(this.calendar.dateCode)
|
||||||
|
|
||||||
|
this.graphCurrentData()
|
||||||
|
|
||||||
|
this.generateTonsOfRandomData()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -231,9 +740,17 @@
|
|||||||
fields: this.fields,
|
fields: this.fields,
|
||||||
cycleData: this.cycleData,
|
cycleData: this.cycleData,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 0 blank, 1 modified, 2 saving, 3 saved
|
||||||
|
this.saving = 2 // Working
|
||||||
|
this.totalEntries = Object.keys(this.cycleData).length
|
||||||
axios.post('/api/cycle-tracking/save', { cycleData:appData })
|
axios.post('/api/cycle-tracking/save', { cycleData:appData })
|
||||||
.then(response => {
|
.then(response => {
|
||||||
{ this.$bus.$emit('notification', 'Data Saved') }
|
// { this.$bus.$emit('notification', 'Data Saved') }
|
||||||
|
this.saving = 3 //Saved
|
||||||
|
setTimeout(() => {
|
||||||
|
this.saving = 0 //Reset
|
||||||
|
}, 2000)
|
||||||
})
|
})
|
||||||
.catch(error => { this.$bus.$emit('notification', error) })
|
.catch(error => { this.$bus.$emit('notification', error) })
|
||||||
},
|
},
|
||||||
@ -241,18 +758,54 @@
|
|||||||
axios.post('/api/cycle-tracking/save', { cycleData:'' })
|
axios.post('/api/cycle-tracking/save', { cycleData:'' })
|
||||||
.then(response => {
|
.then(response => {
|
||||||
{ this.$bus.$emit('notification', 'Data Deleted') }
|
{ this.$bus.$emit('notification', 'Data Deleted') }
|
||||||
|
this.fetchCycleData()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setupFields(){
|
setupFields(){
|
||||||
|
|
||||||
// push the first 3 default fields to users set
|
// push the first 3 default fields to users set
|
||||||
if(this.fields.length == 0){
|
if(this.fields.length == 0){
|
||||||
for (let i = 0; i < 3; i++) {
|
const fieldKeys = Object.keys(this.defaultFields)
|
||||||
this.fields.push(this.defaultFields[i])
|
console.log('Setup default fierds')
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
this.fields.push(fieldKeys[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
generateDateCode(date){
|
||||||
|
|
||||||
|
const dateSetup = [
|
||||||
|
date.getDate(), // 1-31 (Day)
|
||||||
|
date.getMonth()+1, // 0-11 (Month)
|
||||||
|
date.getFullYear(), // 1888-2022 (Year)
|
||||||
|
]
|
||||||
|
|
||||||
|
return dateSetup.join('.')
|
||||||
|
},
|
||||||
|
dateCodeToDate(dateCode){
|
||||||
|
|
||||||
|
const dateChunk = dateCode.split('.')
|
||||||
|
return new Date(dateChunk[2], dateChunk[1]-1, dateChunk[0])
|
||||||
|
},
|
||||||
setupCalendar(date){
|
setupCalendar(date){
|
||||||
|
|
||||||
|
this.working = true
|
||||||
|
setTimeout(() => {
|
||||||
|
this.working = false
|
||||||
|
}, 500)
|
||||||
|
|
||||||
|
if(!date && this.dateObject){
|
||||||
|
date = this.dateObject
|
||||||
|
}
|
||||||
|
if(!date){
|
||||||
|
date = new Date()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.calendar.dateObject = date
|
||||||
|
|
||||||
|
this.calendar.dateCode = this.generateDateCode(date)
|
||||||
|
|
||||||
|
|
||||||
// ------------
|
// ------------
|
||||||
// setup calendar display
|
// setup calendar display
|
||||||
var y = date.getFullYear()
|
var y = date.getFullYear()
|
||||||
@ -272,7 +825,7 @@
|
|||||||
const daysInCurrentMonth = getDaysInMonth(currentYear, currentMonth);
|
const daysInCurrentMonth = getDaysInMonth(currentYear, currentMonth);
|
||||||
|
|
||||||
const monthStartDay = firstDay.getDay()
|
const monthStartDay = firstDay.getDay()
|
||||||
let days = Array(monthStartDay).fill("."); // Pad days to start on correct weekday
|
let days = Array(monthStartDay).fill(""); // Pad days to start on correct weekday
|
||||||
for (let i = 0; i < daysInCurrentMonth; i++) {
|
for (let i = 0; i < daysInCurrentMonth; i++) {
|
||||||
days.push(i+1)
|
days.push(i+1)
|
||||||
}
|
}
|
||||||
@ -291,7 +844,33 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// -------
|
// -------
|
||||||
|
},
|
||||||
|
generateTonsOfRandomData(){
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
let workingDate = new Date()
|
||||||
|
|
||||||
|
for (var i = 0; i < 365 * 2; i++) {
|
||||||
|
|
||||||
|
const cycleTime = (i%30)+1
|
||||||
|
const randomInt = Math.floor(Math.random() * cycleTime+20) + (cycleTime);
|
||||||
|
let randomTemp = parseFloat(`97.${randomInt}`)
|
||||||
|
const randomFive = Math.floor(Math.random() * 4) + 0;
|
||||||
|
const randomHundo = Math.floor(Math.random() * 100) + 1;
|
||||||
|
const randUnoOrDuo = Math.floor(Math.random() * 2) + 1;
|
||||||
|
|
||||||
|
this.cycleData[this.generateDateCode(workingDate)] = {
|
||||||
|
'BT':randomTemp,
|
||||||
|
'CM':randomFive,
|
||||||
|
'SE':randomHundo > 90 ? randUnoOrDuo : 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
workingDate.setDate(workingDate.getDate()-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.graphCurrentData(5000)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -48,7 +48,7 @@ export default new Vuex.Store({
|
|||||||
'small_element_bg_color': '#000',
|
'small_element_bg_color': '#000',
|
||||||
'text_color': '#FFF',
|
'text_color': '#FFF',
|
||||||
'dark_border_color': '#555',//'#ACACAC', //Lighter color to accent elemnts user can interact with
|
'dark_border_color': '#555',//'#ACACAC', //Lighter color to accent elemnts user can interact with
|
||||||
'border_color': '#0b0110',
|
'border_color': '#505050',
|
||||||
'menu-accent': '#626262',
|
'menu-accent': '#626262',
|
||||||
'menu-text': '#d9d9d9',
|
'menu-text': '#d9d9d9',
|
||||||
},
|
},
|
||||||
|
@ -2,12 +2,22 @@
|
|||||||
# Working dev server config
|
# Working dev server config
|
||||||
#
|
#
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name 192.168.1.164;
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
server {
|
server {
|
||||||
|
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
||||||
|
|
||||||
ssl_certificate /home/mab/ss/client/certs/192.168.1.164+4.pem;
|
ssl_certificate /home/mab/ss/client/certs/nginx-selfsigned.crt;
|
||||||
ssl_certificate_key /home/mab/ss/client/certs/192.168.1.164+4-key.pem;
|
ssl_certificate_key /home/mab/ss/client/certs/nginx-selfsigned.key;
|
||||||
|
ssl_dhparam /home/mab/ss/client/certs/dhparam.pem;
|
||||||
|
|
||||||
ssl_session_cache shared:SSL:1m;
|
ssl_session_cache shared:SSL:1m;
|
||||||
ssl_session_timeout 5m;
|
ssl_session_timeout 5m;
|
||||||
ssl_protocols TLSV1.1 TLSV1.2 TLSV1.3;
|
ssl_protocols TLSV1.1 TLSV1.2 TLSV1.3;
|
||||||
@ -67,77 +77,6 @@ server {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
##
|
|
||||||
## Working Copy below --------------------------------------------
|
|
||||||
##
|
|
||||||
|
|
||||||
server {
|
|
||||||
|
|
||||||
listen 443 ssl;
|
|
||||||
|
|
||||||
ssl_certificate /home/mab/ss/client/certs/192.168.1.164+4.pem;
|
|
||||||
ssl_certificate_key /home/mab/ss/client/certs/192.168.1.164+4-key.pem;
|
|
||||||
ssl_session_cache shared:SSL:1m;
|
|
||||||
ssl_session_timeout 5m;
|
|
||||||
ssl_protocols TLSV1.1 TLSV1.2 TLSV1.3;
|
|
||||||
|
|
||||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
||||||
ssl_prefer_server_ciphers on;
|
|
||||||
|
|
||||||
access_log /var/log/nginx/httpslocalhost.access.log;
|
|
||||||
error_log /var/log/nginx/httpslocalhost.error.log;
|
|
||||||
|
|
||||||
client_max_body_size 20M;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_pass https://127.0.0.1:8081;
|
|
||||||
proxy_set_header Host localhost;
|
|
||||||
proxy_set_header X-Forwarded-Host localhost;
|
|
||||||
proxy_set_header X-Forwarded-Server localhost;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_connect_timeout 90s;
|
|
||||||
proxy_read_timeout 90s;
|
|
||||||
proxy_send_timeout 90s;
|
|
||||||
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /sockjs-node {
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-NginX-Proxy true;
|
|
||||||
|
|
||||||
proxy_pass https://127.0.0.1:8081;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /api {
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-NginX-Proxy true;
|
|
||||||
|
|
||||||
proxy_pass http://127.0.0.1:3000;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /socket {
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-NginX-Proxy true;
|
|
||||||
|
|
||||||
proxy_pass http://127.0.0.1:3001;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Prod settings to serve static index
|
# Prod settings to serve static index
|
||||||
|
@ -995,6 +995,7 @@ Note.search = (userId, searchQuery, searchTags, fastFilters, masterKey) => {
|
|||||||
LEFT JOIN attachment ON (note.id = attachment.note_id AND attachment.visible = 1)
|
LEFT JOIN attachment ON (note.id = attachment.note_id AND attachment.visible = 1)
|
||||||
LEFT JOIN user as shareUser ON (note.share_user_id = shareUser.id)
|
LEFT JOIN user as shareUser ON (note.share_user_id = shareUser.id)
|
||||||
WHERE note.user_id = ?
|
WHERE note.user_id = ?
|
||||||
|
AND note.quick_note <= 1
|
||||||
`
|
`
|
||||||
|
|
||||||
//If text search returned results, limit search to those ids
|
//If text search returned results, limit search to those ids
|
||||||
|
Loading…
Reference in New Issue
Block a user