Updated vue CLI to latest version
Added cycle tracking base
@ -11,7 +11,8 @@ echo '-------'
|
|||||||
|
|
||||||
BACKUPDIR="/home/mab/databaseBackupSolidScribe"
|
BACKUPDIR="/home/mab/databaseBackupSolidScribe"
|
||||||
#DEVDBPASS="Crama!Lama*Jamma###88383!!!!!345345956245i"
|
#DEVDBPASS="Crama!Lama*Jamma###88383!!!!!345345956245i"
|
||||||
DEVDBPASS="RootPass1234!"
|
#DEVDBPASS="RootPass1234!"
|
||||||
|
DEVDBPASS="ReallySecureRootPass123!"
|
||||||
# LazaLinga&33Can't!Do!That34
|
# LazaLinga&33Can't!Do!That34
|
||||||
|
|
||||||
cd $BACKUPDIR
|
cd $BACKUPDIR
|
||||||
@ -59,4 +60,4 @@ rm *.sql
|
|||||||
|
|
||||||
echo '-------'
|
echo '-------'
|
||||||
echo "Applied Prod database to Dev. LastFile: $BACKUPFILE"
|
echo "Applied Prod database to Dev. LastFile: $BACKUPFILE"
|
||||||
echo '-------'
|
echo '-------'
|
||||||
|
3
client/.gitignore
vendored
@ -6,6 +6,9 @@ node_modules
|
|||||||
# local env files
|
# local env files
|
||||||
.env.local
|
.env.local
|
||||||
.env.*.local
|
.env.*.local
|
||||||
|
*.pem
|
||||||
|
*.crt
|
||||||
|
*.key
|
||||||
|
|
||||||
# Log files
|
# Log files
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
|
@ -1 +1,19 @@
|
|||||||
# Solid Scribe
|
# client
|
||||||
|
|
||||||
|
## Project setup
|
||||||
|
```
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and hot-reloads for development
|
||||||
|
```
|
||||||
|
npm run serve
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and minifies for production
|
||||||
|
```
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Customize configuration
|
||||||
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC9vBYgeFm2nDnj
|
|
||||||
HJ+Cq4H96adNLrynoFPs0lSxk3YMXG/mP2sXUpqT3P8S7E6QK55IyU0jtiOoYiV1
|
|
||||||
bjcTuDrQyZXrtt+Nz0A7vQxtRu8CatXSEG8Vc3y8QrcDT0HfTezHdNkuJXE8cnYv
|
|
||||||
XSgrZH+cHF996ytOA0lLJWBCHCJH5WIHj5Jziw5dHaLc4mjxSg51xjjqfzLFWQgZ
|
|
||||||
rOPF6lviAWBFux8RIXXg7nClNvEeyikdraZvVuWFgt89KhN/ePU1Xik/o6++evhT
|
|
||||||
HxBZqMQHnTp/4h5T25lPGcs0CPPX0afwNSUdPc8yspuSYNcLsWix3oROLMX6cHBa
|
|
||||||
CTBrtlLzAgMBAAECggEAIBhG7est0dQPfrmCygnVDWyO3mF/jCN0zuStavR0zZZ9
|
|
||||||
X0dvCBzzBPwnMb5Dc+PM/KcAo3/V/E/N4lVof690U4kmER94JXbfeLt79KhBGfmU
|
|
||||||
fdpF0C0e9oGaj7bCf9GgsgS0EDhJNV5vW4e4mc6AP5oVFSnIw4OOzGVgKQ61Rc/e
|
|
||||||
vaalAEz7xGbsYYh2Y43tFnNA6g/qOzs+H8e2Uv+G9mxx7EID1MG3txJJCBpeUeN5
|
|
||||||
JbHQe254IBy4Ko3+i5Tq3ziYL3WyyElCwK5PiRtAP7WNL5AqFT6Fn4L2fULwkTKL
|
|
||||||
sjPSgGxt7QHomeW+12n9bst1mOEmsz0hTGrAtIf1UQKBgQDu1u7BLdTt9H+zaOFl
|
|
||||||
XfhOR3GDZnrIs+F6VuEjdjwNEQLKvOYzGhbgDNRArSETK6f03Jvl7ZC9XYwNC836
|
|
||||||
J29fHsXVcsMJm8fq69PBSdmMXmOpRfjgALu6DYxK1vBqNQ2ToulCwiWoskKEuPUN
|
|
||||||
GwVCc/0HcvwZElWZ1UhsB5Xf9wKBgQDLXfMCtsVpfI15w8qEqRCdrCzprHSitcHJ
|
|
||||||
dCXO72+i9ygMuFtcxo7kgivT0oFUCYmt7Ex+krOlq/xbVLu4sJXWd1FDZ1IeTsIh
|
|
||||||
cuh4IhSOGJR70S4Q/DzbGUQ08Hu+4hrudaw1Y8Fod0wTERCyOIQiWBfKn3Tab3mk
|
|
||||||
X29RdGod5QKBgBig5UHaXgijm79+Yy+2vvIjf9sS6DpmAixBZTno6UxXorgRPpOq
|
|
||||||
bw1vhTueHrkBWXJwhUrycmh0iwqVWwoeoudmHvRhvybwf28EHnPiD6Lf4NsFsiI3
|
|
||||||
MSSAXSUigOwSyHGe7PrLVmLM7vsMr4hIbwRpPYBVJRXYxCb2zV8GcTgFAoGBALiV
|
|
||||||
gWhJNE1We6K1jy9xtF8oU2uU2BiHGGkdPuPgd1dXNca13lcK8c9+RwFv42q/bXOr
|
|
||||||
MpL/3IbW36qV8fzkalvK2LtxIBvaKGHrxgykAjwnGz520nUgPKww9rOGQwsydndR
|
|
||||||
3whmjrme7jGwH5NjsKrrgkyrBojs/V+wL32jSF3xAoGAPLmI5gamjEo9K25ojNxO
|
|
||||||
XjA0fIOxUz/rTPS/qYrxcluXibz8eGXDLq8/D3Q4uWDh18ZQYzWVGoN/x2Qv0srz
|
|
||||||
SHU4AyJo6+asZAe+viOhAtI81B7uM5V4oyEkPaEASPg6+do/to7SFmdcw/XM/p2v
|
|
||||||
KYVXalAeFhW0wJ4I4z6DkuU=
|
|
||||||
-----END PRIVATE KEY-----
|
|
@ -1,26 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIEWTCCAsGgAwIBAgIRAPWg+zwqGDC6qPGon1qGS0cwDQYJKoZIhvcNAQELBQAw
|
|
||||||
czEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSQwIgYDVQQLDBttYWJA
|
|
||||||
bWFydmluIChNYXggR2lhbGFuZWxsYSkxKzApBgNVBAMMIm1rY2VydCBtYWJAbWFy
|
|
||||||
dmluIChNYXggR2lhbGFuZWxsYSkwHhcNMjIwNjI2MTgxMDE5WhcNMjQwOTI2MTgx
|
|
||||||
MDE5WjBPMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUx
|
|
||||||
JDAiBgNVBAsMG21hYkBtYXJ2aW4gKE1heCBHaWFsYW5lbGxhKTCCASIwDQYJKoZI
|
|
||||||
hvcNAQEBBQADggEPADCCAQoCggEBAL28FiB4WbacOeMcn4Krgf3pp00uvKegU+zS
|
|
||||||
VLGTdgxcb+Y/axdSmpPc/xLsTpArnkjJTSO2I6hiJXVuNxO4OtDJleu2343PQDu9
|
|
||||||
DG1G7wJq1dIQbxVzfLxCtwNPQd9N7Md02S4lcTxydi9dKCtkf5wcX33rK04DSUsl
|
|
||||||
YEIcIkflYgePknOLDl0dotziaPFKDnXGOOp/MsVZCBms48XqW+IBYEW7HxEhdeDu
|
|
||||||
cKU28R7KKR2tpm9W5YWC3z0qE3949TVeKT+jr756+FMfEFmoxAedOn/iHlPbmU8Z
|
|
||||||
yzQI89fRp/A1JR09zzKym5Jg1wuxaLHehE4sxfpwcFoJMGu2UvMCAwEAAaOBizCB
|
|
||||||
iDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHwYDVR0jBBgw
|
|
||||||
FoAUzspSlchxoKIVJLKOhPGrcTFjRyowQAYDVR0RBDkwN4IMbWFydmluLmxvY2Fs
|
|
||||||
gglsb2NhbGhvc3SHBMCoAaSHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZI
|
|
||||||
hvcNAQELBQADggGBAAaTOkCKiVwsapOAuiEt8kG7HS/r4HG+drLzhb2dUFYfqxpz
|
|
||||||
mfRlRfFA88JN8nyFtOPcpoeOEaTPMi0hxq0rOw9zHPga5kz6LRAUJeADPgA4pw2S
|
|
||||||
fYT1CEbPMknmHQyhVODKNZN05l3vWC2CL2SDs9lirGVrzmfg7kZ0im8hc81GQgo+
|
|
||||||
MsfnC3AT1r1rzMqGLWiBHM8BjeGGwgqjjFZmxoHuGw+0CuV2TZfkZlNoJRtlRtyV
|
|
||||||
xlkUuRkVDYbLmHLMz7n9+ItOy8epKLToFpIXyhGR+ehAzYyyJeh2SCaboJ71lU+h
|
|
||||||
+90GQPl20ajWzLtwTsZHEAehHu4l/JLWleNaQh3nVdllHyzvU3IR/C7hhVv6im+q
|
|
||||||
/KiwDR3W8LqIOGJsemca5iu73EXd1d5UU49alIPm1Ko+Z22X/WMPj74+9CNW65DV
|
|
||||||
7ebM17NNQgr4tEJdXF3IYwaZ0Epv1/Y7v6bAXT8V2mdjtXfRBwu3HyySl22a9Y4R
|
|
||||||
h7svqj31cb0ubXEfrA==
|
|
||||||
-----END CERTIFICATE-----
|
|
19
client/jsconfig.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "esnext",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lib": [
|
||||||
|
"esnext",
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"scripthost"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
23368
client/package-lock.json
generated
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "solidscribe",
|
"name": "client",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -8,21 +8,19 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.20.0",
|
"axios": "^0.20.0",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.8.3",
|
||||||
"es6-promise": "^4.2.8",
|
"es6-promise": "^4.2.8",
|
||||||
"fomantic-ui-css": "^2.8.7",
|
"fomantic-ui-css": "^2.8.7",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.14",
|
||||||
"vue-router": "^3.2.0",
|
"vue-router": "^3.5.1",
|
||||||
"vuex": "^3.4.0"
|
"vuex": "^3.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vue/cli-plugin-babel": "~5.0.0",
|
||||||
"@vue/cli-plugin-router": "~4.5.0",
|
"@vue/cli-plugin-router": "~5.0.0",
|
||||||
"@vue/cli-plugin-vuex": "~4.5.0",
|
"@vue/cli-plugin-vuex": "~5.0.0",
|
||||||
"@vue/cli-service": "~4.5.0",
|
"@vue/cli-service": "~5.0.0",
|
||||||
"node-sass": "^4.12.0",
|
"vue-template-compiler": "^2.6.14"
|
||||||
"sass-loader": "^8.0.2",
|
|
||||||
"vue-template-compiler": "^2.6.11"
|
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"> 1%",
|
"> 1%",
|
||||||
|
Before Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 799 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.2 KiB |
@ -1,3 +0,0 @@
|
|||||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M8.00251 14.9297L0 1.07422H6.14651L8.00251 4.27503L9.84583 1.07422H16L8.00251 14.9297Z" fill="black"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 215 B |
@ -1,64 +1,17 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<link rel="icon" href="/api/static/assets/favicon.ico" type="image/ico"/>
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
<link rel="shortcut icon" href="/api/static/assets/favicon.ico" type="image/x-icon"/>
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
|
|
||||||
<meta name="theme-color" content="#000" />
|
|
||||||
<link rel="manifest" href="/api/static/assets/manifest.json">
|
|
||||||
|
|
||||||
<title>Solid Scribe - An easy, encrypted Note App</title>
|
|
||||||
<!-- <title><%= htmlWebpackPlugin.options.title %></title> -->
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<noscript>
|
||||||
<!-- placeholder data for scrapers with no JS -->
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||||
<style>
|
</noscript>
|
||||||
body {
|
<div id="app"></div>
|
||||||
background-color: #212221;
|
|
||||||
color: #aeaeae;
|
|
||||||
}
|
|
||||||
.centered {
|
|
||||||
position: fixed;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
text-align: center;
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
}
|
|
||||||
.logo {
|
|
||||||
width: 200px;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
.scrape-info {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="centered">
|
|
||||||
<img class="logo" src="/api/static/assets/logo.svg" alt="Solid Scribe Logo - if you can read this your connection is really slow">
|
|
||||||
<h1>Solid Scribe</h1>
|
|
||||||
<h3>An easy, encrypted Note App</h3>
|
|
||||||
<h4>Loading...</h4>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="scrape-info">
|
|
||||||
<h1>Solid Scribe</h1>
|
|
||||||
<h2>A note application that respects your privacy.</h2>
|
|
||||||
<p>Take notes with a clean editor that works on desktop or mobile.</p>
|
|
||||||
<p>Search notes, links and files to find what you need.</p>
|
|
||||||
<p>Accessable everywhere.</p>
|
|
||||||
<p>Categorize notes with tags.</p>
|
|
||||||
<p>Share data with fellow users.</p>
|
|
||||||
<p>Encrypt notes for additional security.</p>
|
|
||||||
<b>This site requires Javascipt to run.</b>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
font-family: 'Roboto';
|
font-family: 'Roboto';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
src: local('Roboto'), local('Roboto-Regular'), url(/api/static/assets/roboto-latin.woff2) format('woff2');
|
src: local('Roboto'), local('Roboto-Regular'), url(./roboto-latin.woff2) format('woff2');
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
}
|
}
|
||||||
/* latin */
|
/* latin */
|
||||||
@ -11,7 +11,7 @@
|
|||||||
font-family: 'Roboto';
|
font-family: 'Roboto';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
src: local('Roboto Bold'), local('Roboto-Bold'), url(/api/static/assets/roboto-latin-bold.woff2) format('woff2');
|
src: local('Roboto Bold'), local('Roboto-Bold'), url(./roboto-latin-bold.woff2) format('woff2');
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,6 +328,12 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="menu-section" v-if="loggedIn">
|
||||||
|
<router-link class="menu-item menu-button" exact-active-class="active" to="/cycletrack">
|
||||||
|
<i class="calendar check outlin icon"></i>Cycle Track
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="menu-section" v-if="loggedIn">
|
<div class="menu-section" v-if="loggedIn">
|
||||||
<div class="menu-item menu-button" v-on:click="logout()">
|
<div class="menu-item menu-button" v-on:click="logout()">
|
||||||
<i class="log out icon"></i>Log Out
|
<i class="log out icon"></i>Log Out
|
||||||
|
297
client/src/pages/CycletrackingPage.vue
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
<style>
|
||||||
|
.calendar {
|
||||||
|
width: 300px;
|
||||||
|
height: 400px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.day {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 1px solid var(--border_color);
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.2em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.today {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.day ~ .active {
|
||||||
|
|
||||||
|
background-color: var(--main-accent);
|
||||||
|
color: var(--body_bg_color);
|
||||||
|
}
|
||||||
|
.day ~ .has-data {
|
||||||
|
outline: #07f4f4;
|
||||||
|
outline-style: none;
|
||||||
|
outline-width: medium;
|
||||||
|
outline-style: none;
|
||||||
|
outline-offset: -4px;
|
||||||
|
outline-style: solid;
|
||||||
|
outline-width: 2px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="squire-box">
|
||||||
|
|
||||||
|
<h3>Cycle Tracking Beta
|
||||||
|
<span v-on:click="deleteData()">
|
||||||
|
<i class="clickable trash icon"></i>
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="calendar">
|
||||||
|
<p>{{calendar.monthName}}, {{calendar.year}}</p>
|
||||||
|
<div v-for="day in calendar.weekdays" class="day">
|
||||||
|
{{ day }}
|
||||||
|
</div>
|
||||||
|
<div v-for="day in calendar.days" class="day"
|
||||||
|
:class="{
|
||||||
|
'today':day == calendar.today,
|
||||||
|
'active':dateCode == `${day}.${calendar.month}.${calendar.year}`,
|
||||||
|
'has-data':cycleData[`${day}.${calendar.month}.${calendar.year}`],
|
||||||
|
}"
|
||||||
|
v-on:click="openDayData(`${day}.${calendar.month}.${calendar.year}`)">
|
||||||
|
{{ day }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ui form">
|
||||||
|
<h3><input type="text" v-model="dateCode" v-on:keypress.enter="openDayData(dateCode)"></h3>
|
||||||
|
<div class="field" v-for="field in fields">
|
||||||
|
<label>{{ field.label }}</label>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<!-- range -->
|
||||||
|
<div v-if="field.type == 'range' && field.id == key">
|
||||||
|
<div :class="{green:(value == 1)}" v-on:click="saveField(field.id, 1)" class="ui button">1</div>
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<!-- text area -->
|
||||||
|
<div v-if="field.type == 'text' && field.id == key">
|
||||||
|
<textarea rows="3" v-on:keyup="e => saveField(field.id, e.target.value)">
|
||||||
|
{{ value }}
|
||||||
|
</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ui green save button" v-on:click="saveDayData">
|
||||||
|
Save
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CycleTracking',
|
||||||
|
components: {
|
||||||
|
'logo':require('@/components/LogoComponent.vue').default,
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
appWorkingDate: null,
|
||||||
|
fields:[],
|
||||||
|
defaultFields:[
|
||||||
|
{'type':'float','label':'Basil Temp', 'id':'BT'},
|
||||||
|
{'type':'range','label':'Cervical Mucus', 'id':'CM'},
|
||||||
|
{'type':'text','label':'Notes', 'id':'NO'},
|
||||||
|
],
|
||||||
|
cycleData: {},
|
||||||
|
dateCode: null,
|
||||||
|
openDay: [],
|
||||||
|
calendar: {
|
||||||
|
monthName: '',
|
||||||
|
month: '',
|
||||||
|
year: '',
|
||||||
|
days: [],
|
||||||
|
weekdays: ['S','M','T','W','T','F','S'],
|
||||||
|
today: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeCreate() {
|
||||||
|
|
||||||
|
// Perform Login check
|
||||||
|
this.$parent.loginGateway()
|
||||||
|
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
if(!this.$store.getters.getLoggedIn){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup date code
|
||||||
|
// day - month - year
|
||||||
|
const now = new Date()
|
||||||
|
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('.')
|
||||||
|
|
||||||
|
this.setupCalendar(this.appWorkingDate)
|
||||||
|
|
||||||
|
this.fetchCycleData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
saveField(fieldId, value){
|
||||||
|
this.openDay[fieldId] = value
|
||||||
|
},
|
||||||
|
openDayData(dateCode){
|
||||||
|
|
||||||
|
if(String(dateCode).split('.').length != 3){
|
||||||
|
console.log('Invalid Date Code')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dateCode = dateCode || this.dateCode
|
||||||
|
|
||||||
|
let currentDay = this.cycleData[this.dateCode] || {}
|
||||||
|
|
||||||
|
//Set up each entry empty or with current value
|
||||||
|
this.fields.forEach(field => {
|
||||||
|
currentDay[field.id] = currentDay[field.id] || ''
|
||||||
|
})
|
||||||
|
|
||||||
|
this.openDay = currentDay
|
||||||
|
|
||||||
|
},
|
||||||
|
saveDayData(){
|
||||||
|
|
||||||
|
// remove empty keys
|
||||||
|
let cleanDayData = {}
|
||||||
|
Object.keys(this.openDay).forEach(key => {
|
||||||
|
if(this.openDay[key] != ''){
|
||||||
|
cleanDayData[key] = this.openDay[key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.cycleData[this.dateCode] = cleanDayData
|
||||||
|
|
||||||
|
// Update calendar
|
||||||
|
this.setupCalendar(this.appWorkingDate)
|
||||||
|
|
||||||
|
this.saveCycleData()
|
||||||
|
|
||||||
|
},
|
||||||
|
fetchCycleData(){
|
||||||
|
|
||||||
|
axios.post('/api/cycle-tracking/get')
|
||||||
|
.then(({ data }) => {
|
||||||
|
if(data.hasOwnProperty("text")){
|
||||||
|
|
||||||
|
let appData = null
|
||||||
|
try {
|
||||||
|
appData = JSON.parse(data.text)
|
||||||
|
} catch(e) {
|
||||||
|
console.log('Didnt parse json')
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(appData)
|
||||||
|
|
||||||
|
this.cycleData = appData?.cycleData || {}
|
||||||
|
this.fields = appData?.fields || []
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.setupFields()
|
||||||
|
this.openDayData(this.dateCode)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => { this.$bus.$emit('notification', error) })
|
||||||
|
|
||||||
|
},
|
||||||
|
saveCycleData(){
|
||||||
|
|
||||||
|
const appData = JSON.stringify({
|
||||||
|
fields: this.fields,
|
||||||
|
cycleData: this.cycleData,
|
||||||
|
})
|
||||||
|
axios.post('/api/cycle-tracking/save', { cycleData:appData })
|
||||||
|
.then(response => {
|
||||||
|
{ this.$bus.$emit('notification', 'Data Saved') }
|
||||||
|
})
|
||||||
|
.catch(error => { this.$bus.$emit('notification', error) })
|
||||||
|
},
|
||||||
|
deleteData(){
|
||||||
|
axios.post('/api/cycle-tracking/save', { cycleData:'' })
|
||||||
|
.then(response => {
|
||||||
|
{ this.$bus.$emit('notification', 'Data Deleted') }
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setupFields(){
|
||||||
|
|
||||||
|
// push the first 3 default fields to users set
|
||||||
|
if(this.fields.length == 0){
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
this.fields.push(this.defaultFields[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setupCalendar(date){
|
||||||
|
// ------------
|
||||||
|
// setup calendar display
|
||||||
|
var y = date.getFullYear()
|
||||||
|
var m = date.getMonth()
|
||||||
|
|
||||||
|
var firstDay = new Date(y, m, 1);
|
||||||
|
var lastDay = new Date(y, m + 1, 0);
|
||||||
|
|
||||||
|
function getDaysInMonth(year, month) {
|
||||||
|
return new Date(year, month, 0).getDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentYear = date.getFullYear();
|
||||||
|
const currentMonth = date.getMonth() + 1;
|
||||||
|
this.calendar.monthName = date.toLocaleString("en-US", { month: "long" });
|
||||||
|
this.calendar.year = currentYear
|
||||||
|
const daysInCurrentMonth = getDaysInMonth(currentYear, currentMonth);
|
||||||
|
|
||||||
|
const monthStartDay = firstDay.getDay()
|
||||||
|
let days = Array(monthStartDay).fill("."); // Pad days to start on correct weekday
|
||||||
|
for (let i = 0; i < daysInCurrentMonth; i++) {
|
||||||
|
days.push(i+1)
|
||||||
|
}
|
||||||
|
this.calendar.days = days
|
||||||
|
|
||||||
|
// set today
|
||||||
|
this.calendar.today = date.getDate()
|
||||||
|
this.calendar.month = date.getMonth()+1
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
October 2022
|
||||||
|
S M T W T F S
|
||||||
|
1 2 3 4 5 6
|
||||||
|
7 8 9
|
||||||
|
*/
|
||||||
|
|
||||||
|
// -------
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -102,9 +102,9 @@
|
|||||||
|
|
||||||
|
|
||||||
<div class="ui basic fitted right aligned segment" v-if="isFloatingList">
|
<div class="ui basic fitted right aligned segment" v-if="isFloatingList">
|
||||||
<div class="ui small basic green left floated button" v-on:click="closeAllNotes()" v-if="openNotes.length > 1">
|
<div class="ui small basic green left floated button" v-on:click="closeAllNotes()" v-if="openNotes.length >= 1">
|
||||||
<i class="times circle outline icon"></i>
|
<i class="close icon"></i>
|
||||||
Close All
|
Close Notes
|
||||||
</div>
|
</div>
|
||||||
<div class="ui small green button" v-on:click="collapseFloatingList = true">
|
<div class="ui small green button" v-on:click="collapseFloatingList = true">
|
||||||
<i class="caret square left outline icon"></i>
|
<i class="caret square left outline icon"></i>
|
||||||
|
@ -115,5 +115,12 @@ export default new Router({
|
|||||||
meta: {title:'404 Page Not Found'},
|
meta: {title:'404 Page Not Found'},
|
||||||
component: NotFoundPage
|
component: NotFoundPage
|
||||||
},
|
},
|
||||||
|
// Cycle Tracking
|
||||||
|
{
|
||||||
|
path: '/cycletrack',
|
||||||
|
name: 'Cycle Tracking',
|
||||||
|
meta: {title:'Cycle Tracking'},
|
||||||
|
component: () => import(/* webpackChunkName: "CycletrackingPage" */ '@/pages/CycletrackingPage')
|
||||||
|
},
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
@ -1,24 +1,4 @@
|
|||||||
const fs = require('fs')
|
const { defineConfig } = require('@vue/cli-service')
|
||||||
|
module.exports = defineConfig({
|
||||||
module.exports = {
|
transpileDependencies: true
|
||||||
pwa: {
|
})
|
||||||
name: 'SolidScribe',
|
|
||||||
iconPaths: {
|
|
||||||
favicon32: null,
|
|
||||||
favicon16: null,
|
|
||||||
appleTouchIcon: null,
|
|
||||||
maskIcon: null,
|
|
||||||
msTileImage: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
devServer: {
|
|
||||||
disableHostCheck: true,
|
|
||||||
proxy: 'http://localhost:8081',
|
|
||||||
public: 'marvin.local',
|
|
||||||
https: {
|
|
||||||
key: fs.readFileSync('./certs/192.168.1.164+4-key.pem'),
|
|
||||||
cert: fs.readFileSync('./certs/192.168.1.164+4.pem'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
|
2326
package-lock.json
generated
@ -1,7 +1,12 @@
|
|||||||
//Set up environmental variables, pulled from .env file used as process.env.DB_HOST
|
//Set up environmental variables, pulled from ~/.env file used as process.env.DB_HOST
|
||||||
const os = require('os') //Used to get path of home directory
|
const os = require('os') //Used to get path of home directory
|
||||||
const result = require('dotenv').config({ path:(os.homedir()+'/.env') })
|
const result = require('dotenv').config({ path:(os.homedir()+'/.env') })
|
||||||
|
|
||||||
|
const ports = {
|
||||||
|
express: 3000,
|
||||||
|
socketIo: 3001
|
||||||
|
}
|
||||||
|
|
||||||
//Allow user of @ in in require calls. Config in package.json
|
//Allow user of @ in in require calls. Config in package.json
|
||||||
require('module-alias/register')
|
require('module-alias/register')
|
||||||
|
|
||||||
@ -15,7 +20,6 @@ const helmet = require('helmet')
|
|||||||
const express = require('express')
|
const express = require('express')
|
||||||
const app = express()
|
const app = express()
|
||||||
app.use( helmet() )
|
app.use( helmet() )
|
||||||
const port = 3000
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -230,8 +234,8 @@ io.on('connection', function(socket){
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
http.listen(3001, function(){
|
http.listen(ports.socketIo, function(){
|
||||||
console.log('socket.io liseting on port 3001');
|
console.log(`Socke.io: Listening on port ${ports.socketIo}!`)
|
||||||
});
|
});
|
||||||
|
|
||||||
//Enable json body parsing in requests. Allows me to post data in ajax calls
|
//Enable json body parsing in requests. Allows me to post data in ajax calls
|
||||||
@ -285,7 +289,7 @@ UserTest.keyPairTest('genMan30', '1', printResults)
|
|||||||
})
|
})
|
||||||
|
|
||||||
//Test
|
//Test
|
||||||
app.get('/api', (req, res) => res.send('Solidscribe API is up and running'))
|
app.get('/api', (req, res) => res.send('Solidscribe /API is up and running'))
|
||||||
|
|
||||||
//Serve up uploaded files
|
//Serve up uploaded files
|
||||||
app.use('/api/static', express.static( __dirname+'/../staticFiles' ))
|
app.use('/api/static', express.static( __dirname+'/../staticFiles' ))
|
||||||
@ -314,9 +318,13 @@ app.use('/api/attachment', attachment)
|
|||||||
var quickNote = require('@routes/quicknoteController')
|
var quickNote = require('@routes/quicknoteController')
|
||||||
app.use('/api/quick-note', quickNote)
|
app.use('/api/quick-note', quickNote)
|
||||||
|
|
||||||
|
//cycle tracking endpoint
|
||||||
|
var cycleTracking = require('@routes/cycletrackingController')
|
||||||
|
app.use('/api/cycle-tracking', cycleTracking)
|
||||||
|
|
||||||
//Output running status
|
//Output running status
|
||||||
app.listen(port, () => {
|
app.listen(ports.express, () => {
|
||||||
console.log(`Listening on port ${port}!`)
|
console.log(`Express: Listening on port ${ports.express}!`)
|
||||||
})
|
})
|
||||||
|
|
||||||
//
|
//
|
||||||
|
66
server/models/CycleTracking.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
let db = require('@config/database')
|
||||||
|
|
||||||
|
let Note = require('@models/Note')
|
||||||
|
|
||||||
|
let CycleTracking = module.exports = {}
|
||||||
|
|
||||||
|
|
||||||
|
CycleTracking.get = (userId, masterKey) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
|
db.promise()
|
||||||
|
.query(`
|
||||||
|
SELECT note.id FROM note WHERE quick_note = 2 AND user_id = ? LIMIT 1`, [userId])
|
||||||
|
.then((rows, fields) => {
|
||||||
|
|
||||||
|
//Quick Note is set, return note object
|
||||||
|
if(rows[0][0] != undefined){
|
||||||
|
|
||||||
|
let noteId = rows[0][0].id
|
||||||
|
const note = Note.get(userId, noteId, masterKey)
|
||||||
|
.then(noteData => {
|
||||||
|
return resolve(noteData)
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//Or create a new note
|
||||||
|
let finalId = null
|
||||||
|
return Note.create(userId, 'Cycle Tracking', '', masterKey)
|
||||||
|
.then(insertedId => {
|
||||||
|
finalId = insertedId
|
||||||
|
db.promise().query('UPDATE note SET quick_note = 2 WHERE id = ? AND user_id = ?',[insertedId, userId])
|
||||||
|
.then((rows, fields) => {
|
||||||
|
|
||||||
|
const note = Note.get(userId, finalId, masterKey)
|
||||||
|
.then(noteData => {
|
||||||
|
return resolve(noteData)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(console.log)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
CycleTracking.save = (userId, cycleData, masterKey) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
|
let finalId = null
|
||||||
|
|
||||||
|
CycleTracking.get(userId, masterKey)
|
||||||
|
.then(noteObject => {
|
||||||
|
|
||||||
|
return Note.update(userId, noteObject.id, cycleData, noteObject.title, noteObject.color, noteObject.pinned, noteObject.archived, null, masterKey)
|
||||||
|
|
||||||
|
})
|
||||||
|
.then( saveResults => {
|
||||||
|
return resolve(saveResults)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
41
server/routes/cycletrackingController.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// /api/cycle-tracking
|
||||||
|
//
|
||||||
|
|
||||||
|
var express = require('express')
|
||||||
|
var router = express.Router()
|
||||||
|
|
||||||
|
let CycleTracking = require('@models/CycleTracking');
|
||||||
|
|
||||||
|
let userId = null
|
||||||
|
let masterKey = null
|
||||||
|
|
||||||
|
// middleware that is specific to this router
|
||||||
|
router.use(function setUserId (req, res, next) {
|
||||||
|
|
||||||
|
//Session key is required to continue
|
||||||
|
if(!req.headers.sessionId){
|
||||||
|
next('Unauthorized')
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req.headers.userId){
|
||||||
|
userId = req.headers.userId
|
||||||
|
masterKey = req.headers.masterKey
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//Get quick note text
|
||||||
|
router.post('/get', function (req, res) {
|
||||||
|
CycleTracking.get(userId, masterKey)
|
||||||
|
.then( data => res.send(data) )
|
||||||
|
})
|
||||||
|
|
||||||
|
//Push text to quick note
|
||||||
|
router.post('/save', function (req, res) {
|
||||||
|
CycleTracking.save(userId, req.body.cycleData, masterKey)
|
||||||
|
.then( data => res.send(data) )
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = router
|
@ -3,8 +3,9 @@
|
|||||||
cd /home/mab/ss
|
cd /home/mab/ss
|
||||||
|
|
||||||
echo '::--:: Starting dev server. cd client; npm run serve -> 192.168.1.164:8081'
|
echo '::--:: Starting dev server. cd client; npm run serve -> 192.168.1.164:8081'
|
||||||
screen -dmS "NoteClientScreen" bash -c "cd /home/mab/ss/client; npm run serve"
|
screen -dmS "NoteClientScreen" bash -c "cd /home/mab/ss/client; npm run serve -- --port 8081 --https true"
|
||||||
|
|
||||||
echo '::--:: Starting API server (/api), watching for file changes...'
|
echo '::--:: Starting API server (/api), watching for file changes...'
|
||||||
cd /home/mab/ss/server
|
cd /home/mab/ss/server
|
||||||
|
pm2 flush
|
||||||
pm2 start ecosystem.config.js
|
pm2 start ecosystem.config.js
|