-
+
+
+
-
-
diff --git a/client/src/components/NavBar.vue b/client/src/components/NavBar.vue
new file mode 100644
index 0000000..e11af91
--- /dev/null
+++ b/client/src/components/NavBar.vue
@@ -0,0 +1,28 @@
+
+
+
+
\ No newline at end of file
diff --git a/client/src/components/Table.vue b/client/src/components/Table.vue
index 338bd0b..1f1ddec 100644
--- a/client/src/components/Table.vue
+++ b/client/src/components/Table.vue
@@ -2,7 +2,9 @@
Date |
- {{ track.icon }} |
+
+
+ |
@@ -18,6 +20,7 @@
+
+
+ {{props.icon}}
+
+
\ No newline at end of file
diff --git a/client/src/main.ts b/client/src/main.ts
index 26bcf20..90cdedc 100644
--- a/client/src/main.ts
+++ b/client/src/main.ts
@@ -1,6 +1,12 @@
import { createApp } from 'vue'
import './style.scss'
-import App from './App.vue'
+import router from './router'
+import { state } from "./state";
import 'bulma/css/bulma.css'
+import App from './App.vue'
-createApp(App).mount('#app')
+
+const app = createApp(App)
+app.use(router)
+app.mount('#app')
+state.populate()
diff --git a/client/src/router.ts b/client/src/router.ts
new file mode 100644
index 0000000..806e60d
--- /dev/null
+++ b/client/src/router.ts
@@ -0,0 +1,15 @@
+import { createRouter, createWebHistory } from 'vue-router'
+import TableView from './views/TableView.vue'
+import NewTrackView from './views/NewTrackView.vue'
+
+const router = createRouter({
+ history: createWebHistory(),
+ routes: [
+ { path: '/', component: TableView },
+ { path: '/new-track', component: NewTrackView }
+ // for other pages:
+ // {path: '/', component: import('./views/TableView.vue')}
+ ]
+})
+
+export default router
\ No newline at end of file
diff --git a/client/src/state.ts b/client/src/state.ts
index 1b3506b..8d7b479 100644
--- a/client/src/state.ts
+++ b/client/src/state.ts
@@ -1,5 +1,6 @@
import { reactive } from "vue"
import { Track } from "./track"
+import { Tick } from './ticks'
import { error } from "./error"
enum State {
@@ -26,7 +27,7 @@ export const state = reactive({
source.addEventListener('message', event => console.log(event))
source.addEventListener('TickAdded', event => {
console.log(event)
- const tick: Tick = JSON.parse(event.data)
+ const tick: Tick = Tick.fromJSON(JSON.parse(event.data))
const tracks = this.tracks.map(track => {
if (track.id === tick.track_id) {
const ticks = track.ticks ?? []
@@ -38,9 +39,12 @@ export const state = reactive({
})
this.tracks = tracks
})
+ source.addEventListener('TrackAdded', ({ data }) => {
+ const track: Track = Track.fromJSON(JSON.parse(data))
+ this.tracks = [track, ...this.tracks]
+ })
source.addEventListener('TickDropped', event => {
- console.log(event)
- const tick: Tick = JSON.parse(event.data)
+ const tick: Tick = Tick.fromJSON(JSON.parse(event.data))
const tracks = this.tracks.map(track => {
if (track.id === tick.track_id) {
track.ticks = track.ticks?.filter($tick => $tick.id !== tick.id)
@@ -49,6 +53,14 @@ export const state = reactive({
})
this.tracks = tracks
})
+ source.addEventListener('TrackDropped', ({ data }) => {
+ const track: Track = Track.fromJSON(JSON.parse(data))
+ this.tracks = this.tracks.filter($track => $track.id !== track.id)
+ })
+ source.addEventListener('TrackChanged', ({ data }) => {
+ const track: Track = Track.fromJSON(JSON.parse(data))
+ this.tracks = this.tracks.map($track => $track.id === track.id ? track : $track)
+ })
source.addEventListener('Lagged', event => {
console.log(event)
// Refresh the page, refetching the list of tracks and ticks
@@ -85,5 +97,19 @@ export const state = reactive({
const { ok, status, statusText } = await fetch(`/api/v1/tracks/${track.id}/all-ticks?${query.toString()}`, { method: 'DELETE' })
if (!ok)
error(`error deleting ticks for ${track.id}: ${statusText} (${status})`)
+ },
+ async addTrack(track: Track): Promise {
+ const response = await fetch('/api/v1/tracks', {
+ method: "POST",
+ body: JSON.stringify(track),
+ headers: { "Content-Type": "application/json" }
+ })
+ if (!response.ok)
+ error(`error submitting track: ${track}: ${response.statusText} (${response.status})`)
+ return response.ok
+ },
+ async removeTrack(trackID: number) {
+ const response = await fetch(`/api/v1/tracks/${trackID}`, { method: "DELETE" })
+ if (!response.ok) error(`error deleting track with ID ${trackID}: ${response.statusText} (${response.status})`)
}
})
diff --git a/client/src/ticks.ts b/client/src/ticks.ts
index 895682b..d50b9ba 100644
--- a/client/src/ticks.ts
+++ b/client/src/ticks.ts
@@ -1,4 +1,4 @@
-interface ITick {
+export interface ITick {
id: number
track_id?: number
year?: number
@@ -10,7 +10,7 @@ interface ITick {
has_time_info?: number
}
-class Tick implements ITick {
+export class Tick implements ITick {
id: number
track_id?: number
year?: number
diff --git a/client/src/track.ts b/client/src/track.ts
index 14f7567..83947a3 100644
--- a/client/src/track.ts
+++ b/client/src/track.ts
@@ -1,7 +1,7 @@
import { error } from "./error"
export interface ITrack {
- id: number
+ id?: number
name: String
description: String
icon: String
@@ -13,7 +13,7 @@ export interface ITrack {
}
export class Track implements ITrack {
- id: number
+ id?: number
name: String
description: String
icon: String
@@ -24,7 +24,7 @@ export class Track implements ITrack {
ticks?: Array
constructor(
- id: number,
+ id: number | undefined,
name: String,
description: String,
icon: String,
diff --git a/client/src/views/NewTrackView.vue b/client/src/views/NewTrackView.vue
new file mode 100644
index 0000000..8b2ed62
--- /dev/null
+++ b/client/src/views/NewTrackView.vue
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+ TODO color choice
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/src/views/TableView.vue b/client/src/views/TableView.vue
new file mode 100644
index 0000000..053df35
--- /dev/null
+++ b/client/src/views/TableView.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/client/yarn.lock b/client/yarn.lock
index 47e9ec4..a06ffcf 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -213,6 +213,11 @@
"@vue/compiler-dom" "3.3.4"
"@vue/shared" "3.3.4"
+"@vue/devtools-api@^6.5.0":
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz#98b99425edee70b4c992692628fa1ea2c1e57d07"
+ integrity sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==
+
"@vue/reactivity-transform@3.3.4":
version "3.3.4"
resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz#52908476e34d6a65c6c21cd2722d41ed8ae51929"
@@ -522,6 +527,13 @@ vite@^4.3.9:
optionalDependencies:
fsevents "~2.3.2"
+vue-router@4:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.2.2.tgz#b0097b66d89ca81c0986be03da244c7b32a4fd81"
+ integrity sha512-cChBPPmAflgBGmy3tBsjeoe3f3VOSG6naKyY5pjtrqLGbNEXdzCigFUHgBvp9e3ysAtFtEx7OLqcSDh/1Cq2TQ==
+ dependencies:
+ "@vue/devtools-api" "^6.5.0"
+
vue-template-compiler@^2.7.14:
version "2.7.14"
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.7.14.tgz#4545b7dfb88090744c1577ae5ac3f964e61634b1"