264 lines
7.6 KiB
Vue
264 lines
7.6 KiB
Vue
<script setup>
|
|
import { useDatabaseStore } from "@/stores/database"
|
|
import Api from "@/services/Api"
|
|
import appwrite from '@/services/appwrite';
|
|
import { DateTime } from "luxon";
|
|
</script>
|
|
|
|
<script>
|
|
import { defineComponent, toRaw, reactive } from 'vue';
|
|
import { HotTable } from '@handsontable/vue3';
|
|
import { registerAllModules } from 'handsontable/registry';
|
|
import 'handsontable/dist/handsontable.full.css';
|
|
import '../assets/colors.css';
|
|
import Handsontable from 'handsontable/base';
|
|
// register Handsontable's modules
|
|
registerAllModules();
|
|
|
|
function debounce(func, wait, immediate) {
|
|
var timeout;
|
|
return function() {
|
|
var context = this, args = arguments;
|
|
var later = function() {
|
|
timeout = null;
|
|
if (!immediate) func.apply(context, args);
|
|
};
|
|
var callNow = immediate && !timeout;
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(later, wait);
|
|
if (callNow) func.apply(context, args);
|
|
};
|
|
};
|
|
|
|
function getHourClass(i) {
|
|
const colorMapping = {
|
|
0: "black",
|
|
1: "red",
|
|
2: "cyan",
|
|
3: "pink",
|
|
4: "blue",
|
|
5: "green",
|
|
6: "yellow",
|
|
7: "orange",
|
|
8: "purple",
|
|
9: "darkred",
|
|
10: "lime"
|
|
}
|
|
if(i > 10){
|
|
i = Math.round(i/10) - 1
|
|
}
|
|
if (i == null) {
|
|
return "";
|
|
}
|
|
else {
|
|
return "color-" + colorMapping[i];
|
|
}
|
|
}
|
|
|
|
function hourCol(t) {
|
|
return {
|
|
data: "hours." + t,
|
|
type: 'numeric',
|
|
renderer(instance, td, row, col, prop, value) {
|
|
td.className = getHourClass(value);
|
|
td.innerText = value == null ? value : parseFloat(value);
|
|
return td;
|
|
}
|
|
}
|
|
}
|
|
|
|
const colHeaders = ["DATE", "DAY", "12 AM"]
|
|
.concat(Array.from(new Array(11), (x, y) => y+1 + " AM") )
|
|
.concat(Array.from(new Array(12), (x, y) => y+1 + " PM") )
|
|
.concat(["Mood", "Comments"])
|
|
|
|
const ExampleComponent = defineComponent({
|
|
data() {
|
|
return {
|
|
entries: [],
|
|
numEntries: 25,
|
|
offset: 0,
|
|
hotSettings: {
|
|
autoRowSize: true,
|
|
columns: [
|
|
{
|
|
readOnly: true,
|
|
data: "date",
|
|
renderer(instance, td, row, col, prop, value) {
|
|
var date = DateTime.fromISO(value).toUTC().toFormat("MM/dd");
|
|
var today = DateTime.now().toFormat("MM/dd");
|
|
if(today == date){
|
|
td.className = "color-black invert";
|
|
}
|
|
else{td.className = "color-black";}
|
|
td.innerText = date;
|
|
return td;
|
|
}
|
|
},
|
|
{
|
|
readOnly: true,
|
|
data: "date",
|
|
renderer(instance, td, row, col, prop, value) {
|
|
var date = DateTime.fromISO(value).toUTC();
|
|
var today = DateTime.now().toFormat("MM/dd");
|
|
if(date.toFormat("MM/dd") == today){
|
|
td.className = "color-black invert day-of-week";
|
|
}
|
|
else{td.className = "color-black day-of-week";}
|
|
td.innerText = date.toFormat("EEE");
|
|
return td;
|
|
}
|
|
},
|
|
Array.from(new Array(24), (_, t) => hourCol(t)),
|
|
{ data: "mood", type: "numeric" },
|
|
{ data: "comments", className: "align-left" }
|
|
].flat(),
|
|
colHeaders: colHeaders,
|
|
rowHeaders: false,
|
|
readOnly: false,
|
|
width: '100%',
|
|
height: 'auto',
|
|
rowHeights: '22px',
|
|
colWidths(i) {
|
|
if((i > 1) && (i < 26)){
|
|
return "50px";
|
|
}
|
|
else if(i == 27){
|
|
return "1000px";
|
|
}
|
|
else{
|
|
return "50px";
|
|
}
|
|
},
|
|
afterSelection: (row, column, row2, column2, preventScrolling, selectionLayerLevel) => {
|
|
|
|
},
|
|
afterChange: (changes) => {
|
|
this.fixSelectionBug();
|
|
//this.setActiveHourHeader();
|
|
if (changes != null) {
|
|
var entry = this.entries[changes[0][0]];
|
|
entry.date = entry.date.replace(/T.*/, "");
|
|
appwrite.updateEntry(entry);
|
|
}
|
|
},
|
|
licenseKey: 'non-commercial-and-evaluation'
|
|
},
|
|
hotRef: null
|
|
}
|
|
},
|
|
async mounted(){
|
|
this.user = await appwrite.getUser();
|
|
this.entries = await appwrite.getEntries(null,5);
|
|
this.updateTable();
|
|
this.subscribe();
|
|
this.fixSelectionBug();
|
|
},
|
|
created () {
|
|
window.addEventListener('wheel', debounce(this.handleScroll, 300, true));
|
|
},
|
|
unmounted () {
|
|
window.removeEventListener('wheel', debounce(this.handleScroll, 300, true));
|
|
},
|
|
methods: {
|
|
setActiveHourHeader(){
|
|
var timeString = DateTime.now().toFormat("hh a");
|
|
var currentTimeHeader = Array.from(document.querySelectorAll("th"))
|
|
.find(el => el.innerText == timeString);
|
|
currentTimeHeader.className = "invert";
|
|
},
|
|
async handleScroll(e){
|
|
var offset;
|
|
if(e.deltaY > 0){
|
|
var lastDate = DateTime.fromISO(
|
|
this.entries[
|
|
this.hotRef
|
|
.getPlugin('autoRowSize')
|
|
.getLastVisibleRow()
|
|
].date).toUTC().plus({ days: 1 });
|
|
console.log("Grabbing 5 more entries starting at " + lastDate.toISO());
|
|
var newEntries = await appwrite.getEntries(
|
|
lastDate.plus({ days: 1 })
|
|
, 5);
|
|
newEntries.forEach((e) => {
|
|
this.entries.push(e);
|
|
})
|
|
}
|
|
else{
|
|
var firstDate = DateTime.fromISO(
|
|
this.entries[
|
|
this.hotRef
|
|
.getPlugin('autoRowSize')
|
|
.getFirstVisibleRow()
|
|
].date).toUTC().minus({ days: 1 });
|
|
console.log("Grabbing 5 previous entries ending at " + firstDate.toISO());
|
|
var newEntries = await appwrite.getEntries(
|
|
firstDate.minus({ days: 6 })
|
|
, 5);
|
|
var entries = this.entries;
|
|
newEntries.reverse().forEach((e) => {
|
|
entries.unshift(e);
|
|
})
|
|
this.entries = entries;
|
|
}
|
|
},
|
|
fixSelectionBug(){
|
|
if(this.hotRef){
|
|
var offset = (this.hotRef.getRowHeight()) * (this.entries.length + 1) + 2;//document.querySelector(".wtHider").clientHeight;
|
|
document.querySelector(".htBorders div").style.top = "-" + offset + "px";
|
|
}
|
|
},
|
|
subscribe(){
|
|
appwrite.subscribe((payload) => {
|
|
var event = payload.events.filter((e) =>
|
|
e.match(/databases\.\*\.collections\.\*\.documents\.\*\.\w+/)
|
|
)[0].replace(/.+\./,"");
|
|
switch (event) {
|
|
case 'create':
|
|
this.entries.push(payload.payload)
|
|
this.entries = this.entries
|
|
break
|
|
case 'update':
|
|
this.entries = this.entries.map((day) => {
|
|
if (day.$id === payload.payload.$id) {
|
|
return payload.payload
|
|
} else {
|
|
return day
|
|
}
|
|
})
|
|
break
|
|
case 'delete':
|
|
this.entries = this.entries.filter((day) => day.$id !== payload.payload.$id)
|
|
break
|
|
}
|
|
})
|
|
},
|
|
updateTable(){
|
|
this.hotRef = this.$refs.wrapper.hotInstance;
|
|
this.hotRef.loadData(this.entries);
|
|
}
|
|
},
|
|
components: {
|
|
HotTable,
|
|
}
|
|
});
|
|
|
|
export default ExampleComponent;
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<button @click="concatEntries">Fuck</button>
|
|
<!-- <div>{{ entries }}</div>
|
|
|
|
<ul>
|
|
<li v-for="e in entries" :key="e">
|
|
{{ e }}
|
|
</li>
|
|
</ul> -->
|
|
<hot-table ref="wrapper" :settings="hotSettings" :data="entries"></hot-table>
|
|
</template>
|
|
|
|
<style>
|
|
|
|
</style> |