This commit is contained in:
parent
d2fa100a89
commit
2eea51828a
@ -17,29 +17,37 @@ const app = express()
|
|||||||
app.use(morgan('combined'))
|
app.use(morgan('combined'))
|
||||||
app.use(bodyParser.json())
|
app.use(bodyParser.json())
|
||||||
app.use(cors())
|
app.use(cors())
|
||||||
app.get('/database', (req, res) => {
|
|
||||||
const promise = databases.listDocuments('lifetracker-db', 'ryan');
|
// app.get('/database', (req, res) => {
|
||||||
promise.then(function ({ documents } = response) {
|
// const promise = databases.listDocuments('lifetracker-db', 'ryan');
|
||||||
|
// promise.then(function ({ documents } = response) {
|
||||||
|
|
||||||
|
|
||||||
res.send(documents)
|
// res.send(documents)
|
||||||
}, function (error) {
|
// }, function (error) {
|
||||||
console.log(error);
|
// console.log(error);
|
||||||
|
// });
|
||||||
|
// })
|
||||||
|
|
||||||
|
// app.get('/entry/:date', (req, res) => {
|
||||||
|
// var date = new Date(req.params['date']).toISOString().replace(/T.*/,"");
|
||||||
|
// console.log("Fetching entry for " + date);
|
||||||
|
|
||||||
|
// const promise = databases.listDocuments('lifetracker-db', 'ryan');
|
||||||
|
// promise.then(function ({ documents } = response) {
|
||||||
|
|
||||||
|
// entries = documents.map(e => e.Date)
|
||||||
|
// res.send(entries)
|
||||||
|
// }, function (error) {
|
||||||
|
// console.log(error);
|
||||||
|
// });
|
||||||
|
// })
|
||||||
|
|
||||||
|
const path = __dirname + '/dist/'
|
||||||
|
|
||||||
|
app.use(express.static(path))
|
||||||
|
|
||||||
|
app.get(/.*/, function (req,res) {
|
||||||
|
res.sendFile(path + "index.html");
|
||||||
});
|
});
|
||||||
})
|
|
||||||
|
|
||||||
app.get('/entry/:date', (req, res) => {
|
|
||||||
var date = new Date(req.params['date']).toISOString().replace(/T.*/,"");
|
|
||||||
console.log("Fetching entry for " + date);
|
|
||||||
|
|
||||||
const promise = databases.listDocuments('lifetracker-db', 'ryan');
|
|
||||||
promise.then(function ({ documents } = response) {
|
|
||||||
|
|
||||||
entries = documents.map(e => e.Date)
|
|
||||||
res.send(entries)
|
|
||||||
}, function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
app.listen(process.env.PORT || 8081)
|
app.listen(process.env.PORT || 8081)
|
||||||
|
|||||||
226
lifetracker-server/src/dist/assets/index-64281767.js
vendored
Normal file
226
lifetracker-server/src/dist/assets/index-64281767.js
vendored
Normal file
File diff suppressed because one or more lines are too long
41
lifetracker-server/src/dist/assets/index-b41ae507.css
vendored
Normal file
41
lifetracker-server/src/dist/assets/index-b41ae507.css
vendored
Normal file
File diff suppressed because one or more lines are too long
15
lifetracker-server/src/dist/index.html
vendored
Normal file
15
lifetracker-server/src/dist/index.html
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Life Tracker Expanded</title>
|
||||||
|
<script type="module" crossorigin src="/assets/index-64281767.js"></script>
|
||||||
|
<link rel="stylesheet" href="/assets/index-b41ae507.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -8,7 +8,11 @@ const client = new sdk.Client();
|
|||||||
|
|
||||||
const databases = new sdk.Databases(client);
|
const databases = new sdk.Databases(client);
|
||||||
|
|
||||||
|
function importCSV(){
|
||||||
|
console.log("Worked.");
|
||||||
|
}
|
||||||
|
|
||||||
|
function importsCSV(){
|
||||||
var data = fs.readFileSync('data.csv')
|
var data = fs.readFileSync('data.csv')
|
||||||
.toString() // convert Buffer to string
|
.toString() // convert Buffer to string
|
||||||
.split('\n') // split string to lines
|
.split('\n') // split string to lines
|
||||||
@ -41,5 +45,6 @@ var data = fs.readFileSync('data.csv')
|
|||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
exports.entries = data;
|
exports.entries = importCSV;
|
||||||
20
lifetracker-vue/.eslintrc.js
Normal file
20
lifetracker-vue/.eslintrc.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
es2021: true,
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:vue/vue3-recommended",
|
||||||
|
"standard-with-typescript",
|
||||||
|
"prettier",
|
||||||
|
],
|
||||||
|
overrides: [],
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: "latest",
|
||||||
|
sourceType: "module",
|
||||||
|
project: ["tsconfig.json"],
|
||||||
|
},
|
||||||
|
plugins: ["vue"],
|
||||||
|
rules: {},
|
||||||
|
};
|
||||||
1
lifetracker-vue/.prettierrc.json
Normal file
1
lifetracker-vue/.prettierrc.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@ -13,8 +13,8 @@ TypeScript cannot handle type information for `.vue` imports by default, so we r
|
|||||||
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
|
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
|
||||||
|
|
||||||
1. Disable the built-in TypeScript Extension
|
1. Disable the built-in TypeScript Extension
|
||||||
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
|
1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette
|
||||||
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
|
2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
|
||||||
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
||||||
|
|
||||||
## Customize configuration
|
## Customize configuration
|
||||||
|
|||||||
4714
lifetracker-vue/package-lock.json
generated
4714
lifetracker-vue/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,8 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src",
|
||||||
|
"format": "prettier . --write",
|
||||||
"build": "run-p type-check build-only",
|
"build": "run-p type-check build-only",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"build-only": "vite build",
|
"build-only": "vite build",
|
||||||
@ -11,14 +13,18 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@handsontable/vue3": "^12.3.3",
|
"@handsontable/vue3": "^12.3.3",
|
||||||
|
"@vitejs/plugin-react-refresh": "^1.3.6",
|
||||||
"appwrite": "^11.0.0",
|
"appwrite": "^11.0.0",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
|
"eslint-config-standard-with-typescript": "^34.0.1",
|
||||||
|
"eslint-plugin-vue": "^9.12.0",
|
||||||
"handsontable": "^12.3.3",
|
"handsontable": "^12.3.3",
|
||||||
"luxon": "^3.3.0",
|
"luxon": "^3.3.0",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"node": "^20.0.0",
|
"node": "^20.0.0",
|
||||||
"pinia": "^2.0.35",
|
"pinia": "^2.0.35",
|
||||||
"semver": "^7.5.1",
|
"semver": "^7.5.1",
|
||||||
|
"vite-plugin-eslint": "^1.8.1",
|
||||||
"vue": "^3.2.47",
|
"vue": "^3.2.47",
|
||||||
"vue-router": "^4.1.6"
|
"vue-router": "^4.1.6"
|
||||||
},
|
},
|
||||||
@ -26,8 +32,10 @@
|
|||||||
"@types/node": "^18.14.2",
|
"@types/node": "^18.14.2",
|
||||||
"@vitejs/plugin-vue": "^4.0.0",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
"@vue/tsconfig": "^0.1.3",
|
"@vue/tsconfig": "^0.1.3",
|
||||||
|
"eslint-config-prettier": "^8.8.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"typescript": "~4.8.4",
|
"prettier": "2.8.8",
|
||||||
|
"typescript": "^5.1.0-dev.20230515",
|
||||||
"vite": "^4.1.4",
|
"vite": "^4.1.4",
|
||||||
"vue-tsc": "^1.2.0"
|
"vue-tsc": "^1.2.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { RouterLink, RouterView } from 'vue-router'
|
import { RouterLink, RouterView } from "vue-router";
|
||||||
import AuthNav from './components/AuthNav.vue'
|
import AuthNav from "./components/AuthNav.vue";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<header>
|
<header>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<h1>
|
<h1>
|
||||||
<RouterLink to="/">
|
<RouterLink to="/"> Tracker Expanded </RouterLink>
|
||||||
Tracker Expanded
|
|
||||||
</RouterLink>
|
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<nav>
|
<nav>
|
||||||
@ -20,9 +18,6 @@ import AuthNav from './components/AuthNav.vue'
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<RouterView />
|
<RouterView />
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@ -63,8 +63,9 @@ body {
|
|||||||
background: var(--color-background);
|
background: var(--color-background);
|
||||||
transition: color 0.5s, background-color 0.5s;
|
transition: color 0.5s, background-color 0.5s;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
|
font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||||
Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||||
|
sans-serif;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
@ -90,7 +91,6 @@ nav{
|
|||||||
a {
|
a {
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
}
|
}
|
||||||
a.router-link-active {
|
a.router-link-active {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|||||||
@ -13,11 +13,13 @@
|
|||||||
--lime: #bfff55;
|
--lime: #bfff55;
|
||||||
}
|
}
|
||||||
|
|
||||||
.handsontable td.align-left, .handsontable th:last-child div {
|
.handsontable td.align-left,
|
||||||
|
.handsontable th:last-child div {
|
||||||
text-align: left !important;
|
text-align: left !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ht__active_highlight, .ht__highlight {
|
.ht__active_highlight,
|
||||||
|
.ht__highlight {
|
||||||
background: unset;
|
background: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +45,8 @@
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.handsontable td, .handsontable th{
|
.handsontable td,
|
||||||
|
.handsontable th {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
color: var(--white);
|
color: var(--white);
|
||||||
background: var(--black);
|
background: var(--black);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
@import './base.css';
|
@import "./base.css";
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
padding: 1em 2rem;
|
padding: 1em 2rem;
|
||||||
|
|||||||
@ -8,9 +8,7 @@ storeSession.connect();
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="!storeSession.isConnected">
|
<div v-if="!storeSession.isConnected">
|
||||||
<button @click="storeSession.loginAsRyan()">
|
<button @click="storeSession.loginAsRyan()">Connect</button>
|
||||||
Connect
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="storeSession.isConnected">
|
<div v-if="storeSession.isConnected">
|
||||||
Connected as {{ storeSession.session.userId }}.
|
Connected as {{ storeSession.session.userId }}.
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
defineProps<{
|
|
||||||
msg: string
|
|
||||||
}>()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="greetings">
|
|
||||||
<h1 class="green">{{ msg }}</h1>
|
|
||||||
<h3>
|
|
||||||
You’ve successfully created a project with
|
|
||||||
<a href="https://vitejs.dev/" target="_blank" rel="noopener">Vite</a> +
|
|
||||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>. What's next?
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
defineProps<{
|
|
||||||
year: string
|
|
||||||
}>()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<h1 class="green">{{ year }} Tracker Expanded</h1>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="item">
|
|
||||||
<i>
|
|
||||||
<slot name="icon"></slot>
|
|
||||||
</i>
|
|
||||||
<div class="details">
|
|
||||||
<h3>
|
|
||||||
<slot name="heading"></slot>
|
|
||||||
</h3>
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.item {
|
|
||||||
margin-top: 2rem;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.details {
|
|
||||||
flex: 1;
|
|
||||||
margin-left: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
|
||||||
display: flex;
|
|
||||||
place-items: center;
|
|
||||||
place-content: center;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
|
|
||||||
color: var(--color-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: 500;
|
|
||||||
margin-bottom: 0.4rem;
|
|
||||||
color: var(--color-heading);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
.item {
|
|
||||||
margin-top: 0;
|
|
||||||
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
|
||||||
top: calc(50% - 25px);
|
|
||||||
left: -26px;
|
|
||||||
position: absolute;
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
background: var(--color-background);
|
|
||||||
border-radius: 8px;
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item:before {
|
|
||||||
content: ' ';
|
|
||||||
border-left: 1px solid var(--color-border);
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
bottom: calc(50% + 25px);
|
|
||||||
height: calc(50% - 25px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.item:after {
|
|
||||||
content: ' ';
|
|
||||||
border-left: 1px solid var(--color-border);
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: calc(50% + 25px);
|
|
||||||
height: calc(50% - 25px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.item:first-of-type:before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item:last-of-type:after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,13 +1,13 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" href="/favicon.ico">
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Life Tracker Expanded</title>
|
<title>Life Tracker Expanded</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@ -1,12 +1,12 @@
|
|||||||
import { createApp } from 'vue';
|
import { createApp } from "vue";
|
||||||
import { createPinia } from 'pinia';
|
import { createPinia } from "pinia";
|
||||||
|
|
||||||
import App from './App.vue';
|
import App from "./App.vue";
|
||||||
import router from './router';
|
import router from "./router";
|
||||||
|
|
||||||
import './assets/main.css';
|
import "./assets/main.css";
|
||||||
|
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
const app = createApp(App).use(router).use(pinia);
|
const app = createApp(App).use(router).use(pinia);
|
||||||
|
|
||||||
app.mount('#app');
|
app.mount("#app");
|
||||||
|
|||||||
@ -1,39 +1,25 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
import TableView from '../views/TableView.vue'
|
import TableView from "../views/TableView.vue";
|
||||||
import DatabaseView from '../views/DatabaseView.vue'
|
import DatabaseView from "../views/DatabaseView.vue";
|
||||||
import AboutView from '../views/AboutView.vue'
|
|
||||||
import { useSessionStore } from "../stores/session";
|
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: "/",
|
||||||
redirect: '/table'
|
redirect: "/table",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/table',
|
path: "/table",
|
||||||
name: 'table',
|
name: "table",
|
||||||
component: TableView
|
component: TableView,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/database',
|
path: "/database",
|
||||||
name: 'database',
|
name: "database",
|
||||||
component: DatabaseView
|
component: DatabaseView,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
});
|
||||||
|
|
||||||
export default router
|
export default router;
|
||||||
|
|
||||||
|
|
||||||
// router.beforeEach(async (to) => {
|
|
||||||
// // redirect to login page if not logged in and trying to access a restricted page
|
|
||||||
// const publicPages = ['/database'];
|
|
||||||
// const authRequired = !publicPages.includes(to.path);
|
|
||||||
// const auth = useSessionStore();
|
|
||||||
|
|
||||||
// if (authRequired && !auth.session['id']) {
|
|
||||||
// return '/database';
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import axios from 'axios'
|
import axios from "axios";
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
return axios.create({
|
return axios.create({
|
||||||
baseURL: `http://localhost:8081`
|
baseURL: `http://localhost:8081`,
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|||||||
@ -2,83 +2,98 @@ import { Client, Databases, Account, Query } from "appwrite";
|
|||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
|
|
||||||
class AppwriteService {
|
class AppwriteService {
|
||||||
databaseId = 'lifetracker-db';
|
databaseId = "lifetracker-db";
|
||||||
collectionId = "ryan";
|
collectionId = "ryan";
|
||||||
constructor() {
|
constructor() {
|
||||||
this.appwrite = new Client().setEndpoint("http://ryanpandya.com:8080/v1").setProject("lifetracker")
|
this.appwrite = new Client()
|
||||||
|
.setEndpoint("http://ryanpandya.com:8080/v1")
|
||||||
|
.setProject("lifetracker");
|
||||||
this.database = new Databases(this.appwrite);
|
this.database = new Databases(this.appwrite);
|
||||||
this.account = new Account(this.appwrite);
|
this.account = new Account(this.appwrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe = (callback) => {
|
subscribe = (callback) => {
|
||||||
return this.appwrite.subscribe('databases.lifetracker-db.collections.ryan.documents', callback);
|
return this.appwrite.subscribe(
|
||||||
|
"databases.lifetracker-db.collections.ryan.documents",
|
||||||
|
callback
|
||||||
|
);
|
||||||
// "databases.${this.databaseId}.collections.${this.collectionId}.documents", callback);
|
// "databases.${this.databaseId}.collections.${this.collectionId}.documents", callback);
|
||||||
}
|
};
|
||||||
|
|
||||||
addEntry = async ({ date, hours, mood, comments }) => {
|
addEntry = async ({ date, hours, mood, comments }) => {
|
||||||
await this.database.createDocument(this.databaseId, this.collectionId,
|
await this.database.createDocument(
|
||||||
|
this.databaseId,
|
||||||
|
this.collectionId,
|
||||||
date,
|
date,
|
||||||
{ date: new Date(date), hours: hours, mood: mood, comments: comments });
|
{ date: new Date(date), hours, mood, comments }
|
||||||
}
|
);
|
||||||
|
};
|
||||||
|
|
||||||
deleteEntry = async (entryId) => {
|
deleteEntry = async (entryId) => {
|
||||||
await this.database.deleteDocument(this.databaseId, this.collectionId, entryId);
|
await this.database.deleteDocument(
|
||||||
}
|
this.databaseId,
|
||||||
|
this.collectionId,
|
||||||
|
entryId
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
updateEntry = async ({ date, hours, mood, comments }) => {
|
updateEntry = async ({ date, hours, mood, comments }) => {
|
||||||
var hours = JSON.parse("[" + hours + "]")
|
hours = JSON.parse("[" + hours + "]");
|
||||||
await this.database.updateDocument(this.databaseId, this.collectionId,
|
await this.database.updateDocument(
|
||||||
|
this.databaseId,
|
||||||
|
this.collectionId,
|
||||||
date,
|
date,
|
||||||
{ date: new Date(date), hours: hours, mood: mood, comments: comments });
|
{ date: new Date(date), hours, mood, comments }
|
||||||
}
|
);
|
||||||
|
};
|
||||||
|
|
||||||
getUser = async () => {
|
getUser = async () => {
|
||||||
return await this.account.get();
|
return await this.account.get();
|
||||||
}
|
};
|
||||||
|
|
||||||
login = async () => {
|
login = async () => {
|
||||||
await this.account.createAnonymousSession();
|
await this.account.createAnonymousSession();
|
||||||
return await this.getUser();
|
return await this.getUser();
|
||||||
}
|
};
|
||||||
|
|
||||||
getEntries = async (date = null, numEntries = null) => {
|
getEntries = async (date = null, numEntries = null) => {
|
||||||
if (date == null) {
|
if (date == null) {
|
||||||
date = DateTime.fromObject({
|
date = DateTime.fromObject({
|
||||||
year: DateTime.now().toFormat("y"),
|
year: DateTime.now().toFormat("y"),
|
||||||
month: 1,
|
month: 1,
|
||||||
day: 2
|
day: 2,
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
date = DateTime.fromISO(date);
|
date = DateTime.fromISO(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
var firstEntry = (await this.database.listDocuments(
|
const firstEntry = (
|
||||||
this.databaseId, this.collectionId,
|
await this.database.listDocuments(this.databaseId, this.collectionId, [
|
||||||
[Query.orderAsc("date"),Query.limit(1)])
|
Query.orderAsc("date"),
|
||||||
|
Query.limit(1),
|
||||||
|
])
|
||||||
).documents[0];
|
).documents[0];
|
||||||
var referenceDate = DateTime.fromISO(firstEntry.date).toUTC();
|
const referenceDate = DateTime.fromISO(firstEntry.date).toUTC();
|
||||||
|
|
||||||
var offset = Math.floor(date.diff(referenceDate).as("days")) - 1;
|
const offset = Math.floor(date.diff(referenceDate).as("days")) - 1;
|
||||||
|
|
||||||
if (numEntries == null) {
|
if (numEntries == null) {
|
||||||
numEntries = Math.floor(DateTime.now().diff(referenceDate).as("days")) + 7;
|
numEntries =
|
||||||
|
Math.floor(DateTime.now().diff(referenceDate).as("days")) + 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (await this.database.listDocuments(
|
return (
|
||||||
this.databaseId, this.collectionId,
|
await this.database.listDocuments(this.databaseId, this.collectionId, [
|
||||||
[
|
|
||||||
Query.orderAsc("date"),
|
Query.orderAsc("date"),
|
||||||
Query.offset(offset),
|
Query.offset(offset),
|
||||||
Query.limit(numEntries)
|
Query.limit(numEntries),
|
||||||
]
|
])
|
||||||
)
|
|
||||||
).documents;
|
).documents;
|
||||||
}
|
};
|
||||||
|
|
||||||
logout = () => {
|
logout = () => {
|
||||||
return this.appwrite.account.deleteSession('current');
|
return this.appwrite.account.deleteSession("current");
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new AppwriteService()
|
export default new AppwriteService();
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
import type { IEntry } from "@/types/entry";
|
import type { IEntry } from "@/types/entry";
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from "pinia";
|
||||||
import Api from "@/services/Api"
|
import Api from "@/services/Api";
|
||||||
|
|
||||||
export const useDatabaseStore = defineStore({
|
export const useDatabaseStore = defineStore({
|
||||||
id: 'databaseState',
|
id: "databaseState",
|
||||||
state: () => ({
|
state: () => ({
|
||||||
entries: [] as IEntry[]
|
entries: [] as IEntry[],
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
length: (state) => state.entries.length
|
length: (state) => state.entries.length,
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
async fetchEntries() {
|
async fetchEntries() {
|
||||||
@ -18,6 +18,6 @@ export const useDatabaseStore = defineStore({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|||||||
@ -1,34 +1,33 @@
|
|||||||
import type { ISession } from '@/types/session';
|
import type { ISession } from "@/types/session";
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from "pinia";
|
||||||
import { Client, Account, ID } from 'appwrite';
|
import { Client, Account } from "appwrite";
|
||||||
|
|
||||||
const appwriteclient = new Client()
|
const appwriteclient = new Client()
|
||||||
.setEndpoint('http://ryanpandya.com:8080/v1')
|
.setEndpoint("http://ryanpandya.com:8080/v1")
|
||||||
.setProject('lifetracker');
|
.setProject("lifetracker");
|
||||||
|
|
||||||
const account = new Account(appwriteclient);
|
const account = new Account(appwriteclient);
|
||||||
|
|
||||||
export const useSessionStore = defineStore({
|
export const useSessionStore = defineStore({
|
||||||
id: 'sessionState',
|
id: "sessionState",
|
||||||
state: () => ({
|
state: () => ({
|
||||||
session: [] as ISession[],
|
session : {} as ISession
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
isConnected: (state) => state.session['userId'],
|
isConnected: (state) => state.session.userId,
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
logout() {
|
logout() {
|
||||||
const promise = account.deleteSession(this.session['id']);
|
const promise = account.deleteSession(this.session.id);
|
||||||
var self = this;
|
const self = this;
|
||||||
promise.then(
|
promise.then(
|
||||||
function (response) {
|
function (response) {
|
||||||
self.session = [
|
self.session =
|
||||||
{
|
{
|
||||||
email: '',
|
email: "",
|
||||||
userId: '',
|
userId: "",
|
||||||
id: '',
|
id: "",
|
||||||
},
|
}
|
||||||
];
|
|
||||||
console.log(response); // Success
|
console.log(response); // Success
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
@ -37,52 +36,49 @@ export const useSessionStore = defineStore({
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
connect() {
|
connect() {
|
||||||
const promise = account.getSession('current');
|
const promise = account.getSession("current");
|
||||||
var session: ISession = {
|
const session: ISession = {
|
||||||
email: '',
|
email: "",
|
||||||
userId: '',
|
userId: "",
|
||||||
id: '',
|
id: "",
|
||||||
};
|
};
|
||||||
var self = this;
|
const self = this;
|
||||||
promise.then(
|
promise.then(
|
||||||
function (response) {
|
function (response) {
|
||||||
session.email = response.providerUid;
|
session.email = response.providerUid;
|
||||||
session.userId = response.userId;
|
session.userId = response.userId;
|
||||||
session.id = response.$id;
|
session.id = response.$id;
|
||||||
console.log('Connected to existing session');
|
console.log("Connected to existing session");
|
||||||
self.session = session;
|
self.session = session;
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
session.email = null;
|
console.log("No existing session; starting fresh.");
|
||||||
session.userId = null;
|
|
||||||
session.id = '';
|
|
||||||
console.log('No existing session; starting fresh.');
|
|
||||||
self.session = session;
|
self.session = session;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
loginAsRyan() {
|
loginAsRyan() {
|
||||||
this.login('ryan@ryanpandya.com', 'A(84)o9@38appwrite');
|
this.login("ryan@ryanpandya.com", "A(84)o9@38appwrite");
|
||||||
},
|
},
|
||||||
login(email: string, password: string) {
|
login(email: string, password: string) {
|
||||||
console.log(this.session);
|
console.log(this.session);
|
||||||
const promise = account.createEmailSession(email, password);
|
const promise = account.createEmailSession(email, password);
|
||||||
var session: ISession = {
|
const session: ISession = {
|
||||||
email: '',
|
email: "",
|
||||||
userId: '',
|
userId: "",
|
||||||
id: '',
|
id: "",
|
||||||
};
|
};
|
||||||
var self = this;
|
const self = this;
|
||||||
promise.then(
|
promise.then(
|
||||||
function (response) {
|
function (response) {
|
||||||
session.email = response.providerUid;
|
session.email = response.providerUid;
|
||||||
session.userId = response.userId;
|
session.userId = response.userId;
|
||||||
session.id = response.$id;
|
session.id = response.$id;
|
||||||
console.log('Logged in');
|
console.log("Logged in");
|
||||||
self.session = session;
|
self.session = session;
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
console.log('Error');
|
console.log("Error");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
export interface IEntry {
|
export interface IEntry {
|
||||||
date: Date,
|
date: Date;
|
||||||
hours: Number[],
|
hours: Number[];
|
||||||
mood: Number,
|
mood: Number;
|
||||||
note: String
|
note: String;
|
||||||
}
|
}
|
||||||
@ -1,33 +1,33 @@
|
|||||||
<script>
|
<script>
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from "vue";
|
||||||
import { HotTable } from '@handsontable/vue3';
|
import { HotTable } from "@handsontable/vue3";
|
||||||
import { registerAllModules } from 'handsontable/registry';
|
import { registerAllModules } from "handsontable/registry";
|
||||||
import 'handsontable/dist/handsontable.full.css';
|
import "handsontable/dist/handsontable.full.css";
|
||||||
|
|
||||||
// register Handsontable's modules
|
// register Handsontable's modules
|
||||||
registerAllModules();
|
registerAllModules();
|
||||||
|
|
||||||
const ExampleComponent = defineComponent({
|
const ExampleComponent = defineComponent({
|
||||||
|
components: {
|
||||||
|
HotTable,
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hotSettings: {
|
hotSettings: {
|
||||||
data: [
|
data: [
|
||||||
['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1', 'J1'],
|
["A1", "B1", "C1", "D1", "E1", "F1", "G1", "H1", "I1", "J1"],
|
||||||
['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2', 'J2'],
|
["A2", "B2", "C2", "D2", "E2", "F2", "G2", "H2", "I2", "J2"],
|
||||||
['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3', 'J3'],
|
["A3", "B3", "C3", "D3", "E3", "F3", "G3", "H3", "I3", "J3"],
|
||||||
['A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4', 'J4'],
|
["A4", "B4", "C4", "D4", "E4", "F4", "G4", "H4", "I4", "J4"],
|
||||||
['A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5', 'J5'],
|
["A5", "B5", "C5", "D5", "E5", "F5", "G5", "H5", "I5", "J5"],
|
||||||
['A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6', 'H6', 'I6', 'J6'],
|
["A6", "B6", "C6", "D6", "E6", "F6", "G6", "H6", "I6", "J6"],
|
||||||
],
|
],
|
||||||
colHeaders: true,
|
colHeaders: true,
|
||||||
height: 'auto',
|
height: "auto",
|
||||||
licenseKey: 'non-commercial-and-evaluation'
|
licenseKey: "non-commercial-and-evaluation",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
components: {
|
|
||||||
HotTable,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default ExampleComponent;
|
export default ExampleComponent;
|
||||||
@ -38,5 +38,4 @@ export default ExampleComponent;
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style></style>
|
||||||
</style>
|
|
||||||
|
|||||||
@ -1,34 +1,32 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useDatabaseStore } from "@/stores/database"
|
import appwrite from "@/services/appwrite";
|
||||||
import Api from "@/services/Api"
|
|
||||||
import appwrite from '@/services/appwrite';
|
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent, toRaw, reactive } from 'vue';
|
import { defineComponent } from "vue";
|
||||||
import { HotTable } from '@handsontable/vue3';
|
import { HotTable } from "@handsontable/vue3";
|
||||||
import { registerAllModules } from 'handsontable/registry';
|
import { registerAllModules } from "handsontable/registry";
|
||||||
import 'handsontable/dist/handsontable.full.css';
|
import "handsontable/dist/handsontable.full.css";
|
||||||
import '../assets/colors.css';
|
import "../assets/colors.css";
|
||||||
import Handsontable from 'handsontable/base';
|
|
||||||
// register Handsontable's modules
|
// register Handsontable's modules
|
||||||
registerAllModules();
|
registerAllModules();
|
||||||
|
|
||||||
function debounce(func, wait, immediate) {
|
// function debounce(func, wait, immediate) {
|
||||||
var timeout;
|
// let timeout;
|
||||||
return function() {
|
// return function () {
|
||||||
var context = this, args = arguments;
|
// const context = this;
|
||||||
var later = function() {
|
// const args = arguments;
|
||||||
timeout = null;
|
// const later = function () {
|
||||||
if (!immediate) func.apply(context, args);
|
// timeout = null;
|
||||||
};
|
// if (!immediate) func.apply(context, args);
|
||||||
var callNow = immediate && !timeout;
|
// };
|
||||||
clearTimeout(timeout);
|
// const callNow = immediate && !timeout;
|
||||||
timeout = setTimeout(later, wait);
|
// clearTimeout(timeout);
|
||||||
if (callNow) func.apply(context, args);
|
// timeout = setTimeout(later, wait);
|
||||||
};
|
// if (callNow) func.apply(context, args);
|
||||||
};
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
function getHourClass(i) {
|
function getHourClass(i) {
|
||||||
const colorMapping = {
|
const colorMapping = {
|
||||||
@ -42,15 +40,14 @@ function getHourClass(i) {
|
|||||||
7: "orange",
|
7: "orange",
|
||||||
8: "purple",
|
8: "purple",
|
||||||
9: "darkred",
|
9: "darkred",
|
||||||
10: "lime"
|
10: "lime",
|
||||||
}
|
};
|
||||||
if (i > 10) {
|
if (i > 10) {
|
||||||
i = Math.ceil(i/10) - 1
|
i = Math.ceil(i / 10) - 1;
|
||||||
}
|
}
|
||||||
if (i == null) {
|
if (i == null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return "color-" + colorMapping[i];
|
return "color-" + colorMapping[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,21 +55,24 @@ function getHourClass(i) {
|
|||||||
function hourCol(t) {
|
function hourCol(t) {
|
||||||
return {
|
return {
|
||||||
data: "hours." + t,
|
data: "hours." + t,
|
||||||
type: 'numeric',
|
type: "numeric",
|
||||||
renderer(instance, td, row, col, prop, value) {
|
renderer(instance, td, row, col, prop, value) {
|
||||||
td.className = getHourClass(value);
|
td.className = getHourClass(value);
|
||||||
td.innerText = value == null ? value : parseFloat(value);
|
td.innerText = value == null ? value : parseFloat(value);
|
||||||
return td;
|
return td;
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const colHeaders = ["DATE", "DAY", "12 AM"]
|
const colHeaders = ["DATE", "DAY", "12 AM"]
|
||||||
.concat(Array.from(new Array(11), (x, y) => y + 1 + " AM"))
|
.concat(Array.from(new Array(11), (x, y) => y + 1 + " AM"))
|
||||||
.concat(Array.from(new Array(12), (x, y) => y + 1 + " PM"))
|
.concat(Array.from(new Array(12), (x, y) => y + 1 + " PM"))
|
||||||
.concat(["Mood", "Comments"])
|
.concat(["Mood", "Comments"]);
|
||||||
|
|
||||||
const ExampleComponent = defineComponent({
|
const ExampleComponent = defineComponent({
|
||||||
|
components: {
|
||||||
|
HotTable,
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
entries: [],
|
entries: [],
|
||||||
@ -85,67 +85,72 @@ const ExampleComponent = defineComponent({
|
|||||||
readOnly: true,
|
readOnly: true,
|
||||||
data: "date",
|
data: "date",
|
||||||
renderer(instance, td, row, col, prop, value) {
|
renderer(instance, td, row, col, prop, value) {
|
||||||
var date = DateTime.fromISO(value).toUTC().toFormat("MM/dd");
|
const date = DateTime.fromISO(value).toUTC().toFormat("MM/dd");
|
||||||
var today = DateTime.now().toFormat("MM/dd");
|
const today = DateTime.now().toFormat("MM/dd");
|
||||||
if(today == date){
|
if (today === date) {
|
||||||
td.className = "color-black invert";
|
td.className = "color-black invert";
|
||||||
|
} else {
|
||||||
|
td.className = "color-black";
|
||||||
}
|
}
|
||||||
else{td.className = "color-black";}
|
|
||||||
td.innerText = date;
|
td.innerText = date;
|
||||||
return td;
|
return td;
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
data: "date",
|
data: "date",
|
||||||
renderer(instance, td, row, col, prop, value) {
|
renderer(instance, td, row, col, prop, value) {
|
||||||
var date = DateTime.fromISO(value).toUTC();
|
const date = DateTime.fromISO(value).toUTC();
|
||||||
var today = DateTime.now().toFormat("MM/dd");
|
const today = DateTime.now().toFormat("MM/dd");
|
||||||
if(date.toFormat("MM/dd") == today){
|
if (date.toFormat("MM/dd") === today) {
|
||||||
td.className = "color-black invert day-of-week";
|
td.className = "color-black invert day-of-week";
|
||||||
|
} else {
|
||||||
|
td.className = "color-black day-of-week";
|
||||||
}
|
}
|
||||||
else{td.className = "color-black day-of-week";}
|
|
||||||
td.innerText = date.toFormat("EEE");
|
td.innerText = date.toFormat("EEE");
|
||||||
return td;
|
return td;
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
Array.from(new Array(24), (_, t) => hourCol(t)),
|
Array.from(new Array(24), (_, t) => hourCol(t)),
|
||||||
{ data: "mood", type: "numeric" },
|
{ data: "mood", type: "numeric" },
|
||||||
{ data: "comments", className: "align-left" }
|
{ data: "comments", className: "align-left" },
|
||||||
].flat(),
|
].flat(),
|
||||||
colHeaders: colHeaders,
|
colHeaders,
|
||||||
rowHeaders: false,
|
rowHeaders: false,
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
width: '100%',
|
width: "100%",
|
||||||
height: '100%',
|
height: "100%",
|
||||||
rowHeights: '22px',
|
rowHeights: "22px",
|
||||||
colWidths(i) {
|
colWidths(i) {
|
||||||
if((i > 1) && (i < 26)){
|
if (i > 1 && i < 26) {
|
||||||
return "50px";
|
return "50px";
|
||||||
}
|
} else if (i === 27) {
|
||||||
else if(i == 27){
|
|
||||||
return "1000px";
|
return "1000px";
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return "50px";
|
return "50px";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
afterSelection: (row, column, row2, column2, preventScrolling, selectionLayerLevel) => {
|
afterSelection: (
|
||||||
|
row,
|
||||||
},
|
column,
|
||||||
|
row2,
|
||||||
|
column2,
|
||||||
|
preventScrolling,
|
||||||
|
selectionLayerLevel
|
||||||
|
) => {},
|
||||||
afterChange: (changes) => {
|
afterChange: (changes) => {
|
||||||
this.fixSelectionBug();
|
this.fixSelectionBug();
|
||||||
// this.setActiveHourHeader();
|
// this.setActiveHourHeader();
|
||||||
if (changes != null) {
|
if (changes != null) {
|
||||||
var entry = this.entries[changes[0][0]];
|
const entry = this.entries[changes[0][0]];
|
||||||
entry.date = entry.date.replace(/T.*/, "");
|
entry.date = entry.date.replace(/T.*/, "");
|
||||||
appwrite.updateEntry(entry);
|
appwrite.updateEntry(entry);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
licenseKey: 'non-commercial-and-evaluation'
|
licenseKey: "non-commercial-and-evaluation",
|
||||||
},
|
},
|
||||||
hotRef: null
|
hotRef: null,
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
this.user = await appwrite.getUser();
|
this.user = await appwrite.getUser();
|
||||||
@ -168,144 +173,159 @@ const ExampleComponent = defineComponent({
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
selectCurrentCell() {
|
selectCurrentCell() {
|
||||||
var nowRow = this.entries.findIndex((e) =>
|
const nowRow =
|
||||||
DateTime.fromISO(e.date).toISODate() == DateTime.now().toISODate()) - 1;
|
this.entries.findIndex(
|
||||||
var nowCol = parseInt(DateTime.now().toFormat("HH")) + 1;
|
(e) =>
|
||||||
|
DateTime.fromISO(e.date).toISODate() === DateTime.now().toISODate()
|
||||||
|
) - 1;
|
||||||
|
const nowCol = parseInt(DateTime.now().toFormat("HH")) + 1;
|
||||||
this.hotRef.selectCell(nowRow, nowCol);
|
this.hotRef.selectCell(nowRow, nowCol);
|
||||||
},
|
},
|
||||||
scrollToEnd() {
|
scrollToEnd() {
|
||||||
this.hotRef.scrollViewportTo(
|
this.hotRef.scrollViewportTo(this.entries.length - 10);
|
||||||
this.entries.length - 10
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
async lazyLoadEntries() {
|
async lazyLoadEntries() {
|
||||||
var earliestDate = DateTime.fromObject({
|
const earliestDate = DateTime.fromObject({
|
||||||
year: DateTime.now().toFormat("y"),
|
year: DateTime.now().toFormat("y"),
|
||||||
month: 1,
|
month: 1,
|
||||||
day: 1
|
day: 1,
|
||||||
});
|
});
|
||||||
var numEntries = Math.floor(DateTime.now().diff(earliestDate).as("days"));
|
const numEntries = Math.floor(
|
||||||
console.log("Grabbing " + numEntries + " entries starting from " + earliestDate.toISODate());
|
DateTime.now().diff(earliestDate).as("days")
|
||||||
var newEntries = await appwrite.getEntries(
|
);
|
||||||
|
console.log(
|
||||||
|
"Grabbing " +
|
||||||
|
numEntries +
|
||||||
|
" entries starting from " +
|
||||||
|
earliestDate.toISODate()
|
||||||
|
);
|
||||||
|
const newEntries = await appwrite.getEntries(
|
||||||
earliestDate.plus({ days: 1 }),
|
earliestDate.plus({ days: 1 }),
|
||||||
numEntries);
|
numEntries
|
||||||
var entries = this.entries;
|
);
|
||||||
|
const entries = this.entries;
|
||||||
newEntries.reverse().forEach((e) => {
|
newEntries.reverse().forEach((e) => {
|
||||||
entries.unshift(e);
|
entries.unshift(e);
|
||||||
})
|
});
|
||||||
this.entries = entries;
|
this.entries = entries;
|
||||||
this.hotRef.scrollViewportTo(129);
|
this.hotRef.scrollViewportTo(129);
|
||||||
},
|
},
|
||||||
setActiveHourHeader() {
|
setActiveHourHeader() {
|
||||||
var timeString = DateTime.now().toFormat("h a");
|
const timeString = DateTime.now().toFormat("h a");
|
||||||
console.log(timeString);
|
console.log(timeString);
|
||||||
var moot = Array.from(document.querySelectorAll("th"));
|
const moot = Array.from(document.querySelectorAll("th"));
|
||||||
var poot = moot.filter((e) => { return e.innerText == timeString});
|
const poot = moot.filter((e) => {
|
||||||
|
return e.innerText === timeString;
|
||||||
|
});
|
||||||
poot[0].classList.add("active-hour");
|
poot[0].classList.add("active-hour");
|
||||||
},
|
},
|
||||||
async handleScroll(e) {
|
async handleScroll(e) {
|
||||||
if (e.deltaY > 0) {
|
if (e.deltaY > 0) {
|
||||||
var lastDate = DateTime.fromISO(
|
const lastDate = DateTime.fromISO(
|
||||||
this.entries[
|
this.entries[this.hotRef.getPlugin("autoRowSize").getLastVisibleRow()]
|
||||||
this.hotRef
|
.date
|
||||||
.getPlugin('autoRowSize')
|
)
|
||||||
.getLastVisibleRow()
|
.toUTC()
|
||||||
].date).toUTC().plus({ days: 1 });
|
.plus({ days: 1 });
|
||||||
console.log("Grabbing 5 more entries starting at " + lastDate.toISO());
|
console.log("Grabbing 5 more entries starting at " + lastDate.toISO());
|
||||||
var newEntries = await appwrite.getEntries(
|
const newEntries = await appwrite.getEntries(
|
||||||
lastDate.plus({ days: 1 })
|
lastDate.plus({ days: 1 }),
|
||||||
, 5);
|
5
|
||||||
|
);
|
||||||
newEntries.forEach((e) => {
|
newEntries.forEach((e) => {
|
||||||
this.entries.push(e);
|
this.entries.push(e);
|
||||||
})
|
});
|
||||||
}
|
} else {
|
||||||
else{
|
const firstDate = DateTime.fromISO(
|
||||||
var firstDate = DateTime.fromISO(
|
|
||||||
this.entries[
|
this.entries[
|
||||||
this.hotRef
|
this.hotRef.getPlugin("autoRowSize").getFirstVisibleRow()
|
||||||
.getPlugin('autoRowSize')
|
].date
|
||||||
.getFirstVisibleRow()
|
)
|
||||||
].date).toUTC().minus({ days: 1 });
|
.toUTC()
|
||||||
console.log("Grabbing 5 previous entries ending at " + firstDate.toISO());
|
.minus({ days: 1 });
|
||||||
var newEntries = await appwrite.getEntries(
|
console.log(
|
||||||
firstDate.minus({ days: 3 })
|
"Grabbing 5 previous entries ending at " + firstDate.toISO()
|
||||||
, 5);
|
);
|
||||||
var entries = this.entries;
|
const newEntries = await appwrite.getEntries(
|
||||||
|
firstDate.minus({ days: 3 }),
|
||||||
|
5
|
||||||
|
);
|
||||||
|
const entries = this.entries;
|
||||||
newEntries.reverse().forEach((e) => {
|
newEntries.reverse().forEach((e) => {
|
||||||
entries.unshift(e);
|
entries.unshift(e);
|
||||||
})
|
});
|
||||||
this.entries = entries;
|
this.entries = entries;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fixSelectionBug() {
|
fixSelectionBug() {
|
||||||
if (this.hotRef) {
|
if (this.hotRef) {
|
||||||
var offset = (this.hotRef.getRowHeight()) * (this.entries.length + 1) + 2;//document.querySelector(".wtHider").clientHeight;
|
const offset =
|
||||||
document.querySelector(".htBorders div").style.top = "-" + offset + "px";
|
this.hotRef.getRowHeight() * (this.entries.length + 1) + 2; // document.querySelector(".wtHider").clientHeight;
|
||||||
|
document.querySelector(".htBorders div").style.top =
|
||||||
|
"-" + offset + "px";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
subscribe() {
|
subscribe() {
|
||||||
console.log("Subscribing to realtime.");
|
console.log("Subscribing to realtime.");
|
||||||
appwrite.subscribe((payload) => {
|
appwrite.subscribe((payload) => {
|
||||||
var event = payload.events.filter((e) =>
|
const event = payload.events
|
||||||
|
.filter((e) =>
|
||||||
e.match(/databases\.\*\.collections\.\*\.documents\.\*\.\w+/)
|
e.match(/databases\.\*\.collections\.\*\.documents\.\*\.\w+/)
|
||||||
)[0].replace(/.+\./,"");
|
)[0]
|
||||||
|
.replace(/.+\./, "");
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case 'create':
|
case "create":
|
||||||
this.entries.push(payload.payload)
|
this.entries.push(payload.payload);
|
||||||
this.entries = this.entries;
|
|
||||||
this.updateTable();
|
this.updateTable();
|
||||||
break
|
break;
|
||||||
case 'update':
|
case "update":
|
||||||
console.log("Updating");
|
console.log("Updating");
|
||||||
this.entries = this.entries.map((day) => {
|
this.entries = this.entries.map((day) => {
|
||||||
if (day.$id === payload.payload.$id) {
|
if (day.$id === payload.payload.$id) {
|
||||||
return payload.payload
|
return payload.payload;
|
||||||
} else {
|
} else {
|
||||||
return day
|
return day;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.updateTable();
|
this.updateTable();
|
||||||
break
|
break;
|
||||||
case 'delete':
|
case "delete":
|
||||||
this.entries = this.entries.filter((day) => day.$id !== payload.payload.$id);
|
this.entries = this.entries.filter(
|
||||||
|
(day) => day.$id !== payload.payload.$id
|
||||||
|
);
|
||||||
this.updateTable();
|
this.updateTable();
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
updateTable() {
|
updateTable() {
|
||||||
this.hotRef = this.$refs.wrapper.hotInstance;
|
this.hotRef = this.$refs.wrapper.hotInstance;
|
||||||
this.hotRef.loadData(this.entries);
|
this.hotRef.loadData(this.entries);
|
||||||
},
|
},
|
||||||
rewrite(d) {
|
rewrite(d) {
|
||||||
var emptyEntry = {
|
const emptyEntry = {
|
||||||
date: d.toISODate(),
|
date: d.toISODate(),
|
||||||
hours: [],
|
hours: [],
|
||||||
mood: null,
|
mood: null,
|
||||||
comments: ""
|
comments: "",
|
||||||
}
|
};
|
||||||
appwrite.updateEntry(emptyEntry);
|
appwrite.updateEntry(emptyEntry);
|
||||||
console.log("Updated " + d.toISODate());
|
console.log("Updated " + d.toISODate());
|
||||||
},
|
},
|
||||||
rewriteEntries() {
|
rewriteEntries() {
|
||||||
const startDate = DateTime.fromISO("2023-12-10");
|
const startDate = DateTime.fromISO("2023-12-10");
|
||||||
const endDate = DateTime.fromISO("2023-12-31");
|
const endDate = DateTime.fromISO("2023-12-31");
|
||||||
for(var d = startDate; d <= endDate; d = d.plus({days: 1})){
|
for (let d = startDate; d <= endDate; d = d.plus({ days: 1 })) {
|
||||||
setTimeout(this.rewrite(d), 500);
|
setTimeout(this.rewrite(d), 500);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
components: {
|
},
|
||||||
HotTable,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default ExampleComponent;
|
export default ExampleComponent;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button @click="this.setActiveHourHeader()">Fuck</button>
|
|
||||||
<!-- <div>{{ entries }}</div>
|
<!-- <div>{{ entries }}</div>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
@ -314,10 +334,12 @@ export default ExampleComponent;
|
|||||||
</li>
|
</li>
|
||||||
</ul> -->
|
</ul> -->
|
||||||
<div id="table">
|
<div id="table">
|
||||||
<hot-table ref="wrapper" :settings="hotSettings" :data="entries"></hot-table>
|
<hot-table
|
||||||
|
ref="wrapper"
|
||||||
|
:settings="hotSettings"
|
||||||
|
:data="entries"
|
||||||
|
></hot-table>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@ -6,7 +6,9 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
"noImplicitAny": false
|
"noImplicitAny": false,
|
||||||
|
"ignoreDeprecations": "5.0",
|
||||||
|
"allowJs": true
|
||||||
},
|
},
|
||||||
|
|
||||||
"references": [
|
"references": [
|
||||||
|
|||||||
@ -1,8 +1,14 @@
|
|||||||
{
|
{
|
||||||
"extends": "@vue/tsconfig/tsconfig.node.json",
|
"extends": "@vue/tsconfig/tsconfig.node.json",
|
||||||
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
|
"include": [
|
||||||
|
"vite.config.*",
|
||||||
|
"vitest.config.*",
|
||||||
|
"cypress.config.*",
|
||||||
|
"playwright.config.*"
|
||||||
|
],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"composite": true,
|
"composite": true,
|
||||||
"types": ["node"]
|
"types": ["node"],
|
||||||
|
"ignoreDeprecations": "5.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,24 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from "node:url";
|
||||||
|
import { defineConfig } from "vite";
|
||||||
import { defineConfig } from 'vite'
|
import eslintPlugin from "vite-plugin-eslint";
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from "@vitejs/plugin-vue";
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue()],
|
plugins: [vue()],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
"@": fileURLToPath(new URL("./src", import.meta.url)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
root: "src",
|
||||||
|
build: {
|
||||||
|
outDir: "../../lifetracker-server/dist",
|
||||||
|
emptyOutDir: true,
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
hmr: {
|
||||||
|
overlay: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user