Messy transition to Vue
This commit is contained in:
parent
aed2080b53
commit
b0c3eaf33d
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
/env
|
/env
|
||||||
|
|
||||||
|
/node_modules
|
||||||
@ -1,4 +1,5 @@
|
|||||||
from flask import Flask
|
from flask import Flask, jsonify
|
||||||
|
from flask_cors import CORS
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@ -7,6 +8,9 @@ persistent_path = os.getenv(
|
|||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
# enable CORS
|
||||||
|
CORS(app, resources={r'/*': {'origins': '*'}})
|
||||||
|
|
||||||
db_path = os.path.join(persistent_path, "sqlite.db")
|
db_path = os.path.join(persistent_path, "sqlite.db")
|
||||||
|
|
||||||
app.config["SQLALCHEMY_DATABASE_URI"] = f'sqlite:///{db_path}'
|
app.config["SQLALCHEMY_DATABASE_URI"] = f'sqlite:///{db_path}'
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -6,6 +6,7 @@
|
|||||||
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
|
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
|
||||||
<!-- HTMX -->
|
<!-- HTMX -->
|
||||||
<script src="https://unpkg.com/htmx.org@1.5.0"></script>
|
<script src="https://unpkg.com/htmx.org@1.5.0"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
|
||||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.js"></script>
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.js"></script>
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.css" />
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.css" />
|
||||||
<link rel="stylesheet" href="/colors.css"/>
|
<link rel="stylesheet" href="/colors.css"/>
|
||||||
|
|||||||
@ -1,26 +1,8 @@
|
|||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<div id="app">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="container"></div>
|
|
||||||
|
|
||||||
<script language="javascript">
|
|
||||||
const container = document.querySelector('#container');
|
|
||||||
const data = [
|
|
||||||
{ id: 1, name: 'Ted Right', address: '' },
|
|
||||||
{ id: 2, name: 'Frank Honest', address: '' },
|
|
||||||
{ id: 3, name: 'Joan Well', address: '' },
|
|
||||||
{ id: 4, name: 'Gail Polite', address: '' },
|
|
||||||
{ id: 5, name: 'Michael Fair', address: '' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const hot = new Handsontable(container, {
|
|
||||||
data,
|
|
||||||
colHeaders: false,
|
|
||||||
height: 'auto',
|
|
||||||
width: 'auto',
|
|
||||||
minSpareRows: 1,
|
|
||||||
licenseKey: 'non-commercial-and-evaluation'
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
28
lifetracker-vue/.gitignore
vendored
Normal file
28
lifetracker-vue/.gitignore
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
.DS_Store
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
coverage
|
||||||
|
*.local
|
||||||
|
|
||||||
|
/cypress/videos/
|
||||||
|
/cypress/screenshots/
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
3
lifetracker-vue/.vscode/extensions.json
vendored
Normal file
3
lifetracker-vue/.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
|
||||||
|
}
|
||||||
40
lifetracker-vue/README.md
Normal file
40
lifetracker-vue/README.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# lifetracker-vue
|
||||||
|
|
||||||
|
This template should help get you started developing with Vue 3 in Vite.
|
||||||
|
|
||||||
|
## Recommended IDE Setup
|
||||||
|
|
||||||
|
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||||
|
|
||||||
|
## Type Support for `.vue` Imports in TS
|
||||||
|
|
||||||
|
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
|
||||||
|
|
||||||
|
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) 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. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
||||||
|
|
||||||
|
## Customize configuration
|
||||||
|
|
||||||
|
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
||||||
|
|
||||||
|
## Project Setup
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compile and Hot-Reload for Development
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Type-Check, Compile and Minify for Production
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
1
lifetracker-vue/env.d.ts
vendored
Normal file
1
lifetracker-vue/env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
13
lifetracker-vue/index.html
Normal file
13
lifetracker-vue/index.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!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>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4199
lifetracker-vue/package-lock.json
generated
Normal file
4199
lifetracker-vue/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
29
lifetracker-vue/package.json
Normal file
29
lifetracker-vue/package.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"name": "lifetracker-vue",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "run-p type-check build-only",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"build-only": "vite build",
|
||||||
|
"type-check": "vue-tsc --noEmit"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@handsontable/vue3": "^12.3.3",
|
||||||
|
"appwrite": "^11.0.0",
|
||||||
|
"handsontable": "^12.3.3",
|
||||||
|
"pinia": "^2.0.35",
|
||||||
|
"vue": "^3.2.47",
|
||||||
|
"vue-router": "^4.1.6"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^18.14.2",
|
||||||
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
|
"@vue/tsconfig": "^0.1.3",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
|
"typescript": "~4.8.4",
|
||||||
|
"vite": "^4.1.4",
|
||||||
|
"vue-tsc": "^1.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
lifetracker-vue/public/favicon.ico
Normal file
BIN
lifetracker-vue/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
28
lifetracker-vue/src/App.vue
Normal file
28
lifetracker-vue/src/App.vue
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { RouterLink, RouterView } from 'vue-router'
|
||||||
|
import AuthNav from './components/AuthNav.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<header>
|
||||||
|
<div class="title">
|
||||||
|
<h1>
|
||||||
|
<RouterLink to="/">
|
||||||
|
{{ year }} Tracker Expanded
|
||||||
|
</RouterLink>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<nav>
|
||||||
|
<RouterLink to="/table">Table</RouterLink>
|
||||||
|
<RouterLink to="/database">Database Info</RouterLink>
|
||||||
|
</nav>
|
||||||
|
<AuthNav />
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<RouterView />
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
101
lifetracker-vue/src/assets/base.css
Normal file
101
lifetracker-vue/src/assets/base.css
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/* color palette from <https://github.com/vuejs/theme> */
|
||||||
|
:root {
|
||||||
|
--vt-c-white: #ffffff;
|
||||||
|
--vt-c-white-soft: #f8f8f8;
|
||||||
|
--vt-c-white-mute: #f2f2f2;
|
||||||
|
|
||||||
|
--vt-c-black: #181818;
|
||||||
|
--vt-c-black-soft: #222222;
|
||||||
|
--vt-c-black-mute: #282828;
|
||||||
|
|
||||||
|
--vt-c-indigo: #2c3e50;
|
||||||
|
|
||||||
|
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
||||||
|
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
||||||
|
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
||||||
|
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
||||||
|
|
||||||
|
--vt-c-text-light-1: var(--vt-c-indigo);
|
||||||
|
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
||||||
|
--vt-c-text-dark-1: var(--vt-c-white);
|
||||||
|
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
||||||
|
|
||||||
|
--black: #273036;
|
||||||
|
--red: #c71634;
|
||||||
|
--cyan: #005744;
|
||||||
|
--pink: #ff65ae;
|
||||||
|
--blue: #00a9b3;
|
||||||
|
--green: #189749;
|
||||||
|
--yellow: #fff336;
|
||||||
|
--orange: #ff6d01;
|
||||||
|
--purple: #5b3ab1;
|
||||||
|
--darkred: #ff2816;
|
||||||
|
--lime: #bfff55;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* semantic color variables for this project */
|
||||||
|
:root {
|
||||||
|
--color-background: var(--black);
|
||||||
|
--color-background-soft: var(--vt-c-black-soft);
|
||||||
|
--color-background-mute: var(--vt-c-black-mute);
|
||||||
|
|
||||||
|
--color-border: var(--vt-c-divider-dark-2);
|
||||||
|
--color-border-hover: var(--vt-c-divider-dark-1);
|
||||||
|
|
||||||
|
--color-heading: var(--vt-c-text-dark-1);
|
||||||
|
--color-text: var(--vt-c-text-dark-2);
|
||||||
|
|
||||||
|
--section-gap: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
position: relative;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
min-height: 100vh;
|
||||||
|
color: var(--color-text);
|
||||||
|
background: var(--color-background);
|
||||||
|
transition: color 0.5s, background-color 0.5s;
|
||||||
|
line-height: 1.6;
|
||||||
|
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
|
||||||
|
Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||||
|
font-size: 15px;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
header{
|
||||||
|
display: flex;
|
||||||
|
gap: 2em;
|
||||||
|
align-items: center;
|
||||||
|
/* border-bottom: 1px solid var(--vt-c-white-mute); */
|
||||||
|
}
|
||||||
|
|
||||||
|
h1{
|
||||||
|
color: var(--vt-c-text-dark-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
nav{
|
||||||
|
display:flex;
|
||||||
|
gap: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a{
|
||||||
|
color: var(--color-text);
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
}
|
||||||
|
a.router-link-active{
|
||||||
|
font-weight: bold;
|
||||||
|
border-bottom: 1px solid var(--color-text);
|
||||||
|
}
|
||||||
|
a:hover{
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
1
lifetracker-vue/src/assets/logo.svg
Normal file
1
lifetracker-vue/src/assets/logo.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
||||||
|
After Width: | Height: | Size: 276 B |
7
lifetracker-vue/src/assets/main.css
Normal file
7
lifetracker-vue/src/assets/main.css
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
@import './base.css';
|
||||||
|
|
||||||
|
#app {
|
||||||
|
padding: 1em 2rem;
|
||||||
|
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
8
lifetracker-vue/src/components/AuthNav.vue
Normal file
8
lifetracker-vue/src/components/AuthNav.vue
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<script>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="year == 2023">
|
||||||
|
You are not logged in.
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
20
lifetracker-vue/src/components/HelloWorld.vue
Normal file
20
lifetracker-vue/src/components/HelloWorld.vue
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<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>
|
||||||
13
lifetracker-vue/src/components/Interface.vue
Normal file
13
lifetracker-vue/src/components/Interface.vue
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
defineProps<{
|
||||||
|
year: string
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<h1 class="green">{{ year }} Tracker Expanded</h1>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
86
lifetracker-vue/src/components/WelcomeItem.vue
Normal file
86
lifetracker-vue/src/components/WelcomeItem.vue
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<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>
|
||||||
15
lifetracker-vue/src/main.ts
Normal file
15
lifetracker-vue/src/main.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { createApp } from 'vue'
|
||||||
|
import { createPinia } from 'pinia'
|
||||||
|
|
||||||
|
import App from './App.vue'
|
||||||
|
import router from './router'
|
||||||
|
|
||||||
|
import './assets/main.css'
|
||||||
|
|
||||||
|
const pinia = createPinia()
|
||||||
|
const app = createApp(App)
|
||||||
|
|
||||||
|
app.use(router)
|
||||||
|
app.use(pinia)
|
||||||
|
|
||||||
|
app.mount('#app')
|
||||||
26
lifetracker-vue/src/router/index.ts
Normal file
26
lifetracker-vue/src/router/index.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
import TableView from '../views/TableView.vue'
|
||||||
|
import DatabaseView from '../views/DatabaseView.vue'
|
||||||
|
import AboutView from '../views/AboutView.vue'
|
||||||
|
|
||||||
|
const router = createRouter({
|
||||||
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
redirect: '/table'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/table',
|
||||||
|
name: 'table',
|
||||||
|
component: TableView
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/database',
|
||||||
|
name: 'database',
|
||||||
|
component: DatabaseView
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
export default router
|
||||||
15
lifetracker-vue/src/views/AboutView.vue
Normal file
15
lifetracker-vue/src/views/AboutView.vue
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<template>
|
||||||
|
<div class="about">
|
||||||
|
<h1>This is an about page</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.about {
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
102
lifetracker-vue/src/views/DatabaseView.vue
Normal file
102
lifetracker-vue/src/views/DatabaseView.vue
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<script>
|
||||||
|
// Try to connect
|
||||||
|
import { Client, Account, ID } from 'appwrite';
|
||||||
|
|
||||||
|
const appwriteclient = new Client()
|
||||||
|
.setEndpoint('http://ryanpandya.com:8080/v1') // Your API Endpoint
|
||||||
|
.setProject('lifetracker'); // Your project ID
|
||||||
|
|
||||||
|
const account = new Account(appwriteclient);
|
||||||
|
var email; var userId; var password; var session;
|
||||||
|
export default {
|
||||||
|
mounted(){
|
||||||
|
const promise = account.getSession('current');
|
||||||
|
var self = this;
|
||||||
|
promise.then(function (response) {
|
||||||
|
self.email = response.providerUid;
|
||||||
|
self.userId = response.userId;
|
||||||
|
self.session = response.$id;
|
||||||
|
}, function (error) {
|
||||||
|
self.email = null;
|
||||||
|
self.userId = null;
|
||||||
|
self.password = null;
|
||||||
|
self.session = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
userId: userId,
|
||||||
|
email: email,
|
||||||
|
password: password,
|
||||||
|
error: null,
|
||||||
|
session: session,
|
||||||
|
account: account
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
connect() {
|
||||||
|
const promise = this.account.createEmailSession(this.email, this.password);
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
promise.then(function (response) {
|
||||||
|
self.session = response;
|
||||||
|
self.userId = response.userId;
|
||||||
|
self.error = false;
|
||||||
|
|
||||||
|
}, function (error) {
|
||||||
|
self.session = false;
|
||||||
|
self.error = error;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
logout() {
|
||||||
|
|
||||||
|
|
||||||
|
const promise = this.account.deleteSession(this.session);
|
||||||
|
var self = this;
|
||||||
|
promise.then(function (response) {
|
||||||
|
self.userId = null; self.email = null; self.session = false;
|
||||||
|
console.log(response); // Success
|
||||||
|
}, function (error) {
|
||||||
|
console.log(error); // Failure
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div v-if="session == null">
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
<div v-if="session==false" id="form">
|
||||||
|
<h2>Not connected yet.</h2>
|
||||||
|
<div id="login">
|
||||||
|
<input name="email" type="text" v-model="email" placeholder="email" />
|
||||||
|
<input name="password" type="password" v-model="password" placeholder="password"/>
|
||||||
|
<button @click="connect">Connect to database</button>
|
||||||
|
<h3 class="error" v-if="error">{{ error }}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="session">
|
||||||
|
<h2>Welcome back, {{ userId }}!</h2>
|
||||||
|
<div class="flex">
|
||||||
|
<button @click="logout">Log Out</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div#form{
|
||||||
|
display:flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1em;
|
||||||
|
width: 200px;
|
||||||
|
|
||||||
|
}
|
||||||
|
h3.error{
|
||||||
|
color: var(--darkred);
|
||||||
|
}
|
||||||
|
div#login{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
9
lifetracker-vue/src/views/HomeView.vue
Normal file
9
lifetracker-vue/src/views/HomeView.vue
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import TheWelcome from '../components/TheWelcome.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<main>
|
||||||
|
<TheWelcome />
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
49
lifetracker-vue/src/views/TableView.vue
Normal file
49
lifetracker-vue/src/views/TableView.vue
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<template>
|
||||||
|
<hot-table :settings="hotSettings" :data="data"></hot-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script scoped>
|
||||||
|
import { Client, Account, ID } from 'appwrite';
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { HotTable } from '@handsontable/vue3';
|
||||||
|
import { registerAllModules } from 'handsontable/registry';
|
||||||
|
import 'handsontable/dist/handsontable.full.css';
|
||||||
|
|
||||||
|
// register Handsontable's modules
|
||||||
|
registerAllModules();
|
||||||
|
|
||||||
|
const appwriteclient = new Client();
|
||||||
|
|
||||||
|
appwriteclient
|
||||||
|
.setEndpoint('http://ryanpandya.com:8080/v1')
|
||||||
|
.setProject('lifetracker');
|
||||||
|
|
||||||
|
const ExampleComponent = defineComponent({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
hotSettings: {
|
||||||
|
data: [
|
||||||
|
['DATE', 'DAY',
|
||||||
|
'12 AM', '1 AM', '2 AM', '3 AM', '4 AM', '5 AM', '6 AM', '7 AM', '8 AM', '9 AM', '10 AM', '11 AM',
|
||||||
|
'12 PM', '1 PM', '2 PM', '3 PM', '4 PM', '5 PM', '6 PM', '7 PM', '8 PM', '9 PM', '10 PM', '11 PM',
|
||||||
|
'Mood', 'Notes'
|
||||||
|
],
|
||||||
|
['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2', 'J2'],
|
||||||
|
['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3', 'J3'],
|
||||||
|
['A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4', 'J4'],
|
||||||
|
['A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5', 'J5'],
|
||||||
|
['A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6', 'H6', 'I6', 'J6'],
|
||||||
|
],
|
||||||
|
colHeaders: false,
|
||||||
|
height: 'auto',
|
||||||
|
licenseKey: 'non-commercial-and-evaluation'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
HotTable,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ExampleComponent;
|
||||||
|
</script>
|
||||||
17
lifetracker-vue/tsconfig.json
Normal file
17
lifetracker-vue/tsconfig.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"extends": "@vue/tsconfig/tsconfig.web.json",
|
||||||
|
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
},
|
||||||
|
"noImplicitAny": false
|
||||||
|
},
|
||||||
|
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.node.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
8
lifetracker-vue/tsconfig.node.json
Normal file
8
lifetracker-vue/tsconfig.node.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": "@vue/tsconfig/tsconfig.node.json",
|
||||||
|
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"types": ["node"]
|
||||||
|
}
|
||||||
|
}
|
||||||
14
lifetracker-vue/vite.config.ts
Normal file
14
lifetracker-vue/vite.config.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
|
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [vue()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
47
package-lock.json
generated
Normal file
47
package-lock.json
generated
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"name": "ltx",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"node": "^20.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node": {
|
||||||
|
"version": "20.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node/-/node-20.0.0.tgz",
|
||||||
|
"integrity": "sha512-4R1vw5hKUjQw3x65x9g/ape/XlY/ZFHaQWB+jQLFJIJkVKJPDSY4oj3O6qgXOvv2wwgEpK9J2SvJUjuL6zu0uA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"node-bin-setup": "^1.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"node": "bin/node"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"npm": ">=5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-bin-setup": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-bin-setup/-/node-bin-setup-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-opgw9iSCAzT2+6wJOETCpeRYAQxSopqQ2z+N6BXwIMsQQ7Zj5M8MaafQY8JMlolRR6R1UXg2WmhKp0p9lSOivg=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"node": {
|
||||||
|
"version": "20.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node/-/node-20.0.0.tgz",
|
||||||
|
"integrity": "sha512-4R1vw5hKUjQw3x65x9g/ape/XlY/ZFHaQWB+jQLFJIJkVKJPDSY4oj3O6qgXOvv2wwgEpK9J2SvJUjuL6zu0uA==",
|
||||||
|
"requires": {
|
||||||
|
"node-bin-setup": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node-bin-setup": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-bin-setup/-/node-bin-setup-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-opgw9iSCAzT2+6wJOETCpeRYAQxSopqQ2z+N6BXwIMsQQ7Zj5M8MaafQY8JMlolRR6R1UXg2WmhKp0p9lSOivg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
package.json
Normal file
5
package.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"node": "^20.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user