diff --git a/CMD_HISTORY.md b/CMD_HISTORY.md
index ae6c175..547777e 100644
--- a/CMD_HISTORY.md
+++ b/CMD_HISTORY.md
@@ -55,3 +55,10 @@ Commands were run in the order listed below on a debian based system.
cd frontend
pnpm install
```
+
+- Add Vue-router & Villus
+ ```bash
+ cd frontend
+ pnpm install villus graphql
+ pnpm install graphql-tag
+ ```
diff --git a/frontend/index.html b/frontend/index.html
index 8388c4b..6882883 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -2,9 +2,9 @@
-
+
- Vite + Vue
+ YetAnotherTodoList
diff --git a/frontend/package.json b/frontend/package.json
index 7f1fcd7..2943b8c 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -9,7 +9,11 @@
"preview": "vite preview"
},
"dependencies": {
- "vue": "^3.3.4"
+ "graphql": "^16.8.1",
+ "graphql-tag": "^2.12.6",
+ "villus": "^3.2.0",
+ "vue": "^3.3.4",
+ "vue-router": "^4.2.5"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.2.3",
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index 526ca93..b76e2d2 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -5,9 +5,21 @@ settings:
excludeLinksFromLockfile: false
dependencies:
+ graphql:
+ specifier: ^16.8.1
+ version: 16.8.1
+ graphql-tag:
+ specifier: ^2.12.6
+ version: 2.12.6(graphql@16.8.1)
+ villus:
+ specifier: ^3.2.0
+ version: 3.2.0(graphql@16.8.1)(vue@3.3.6)
vue:
specifier: ^3.3.4
version: 3.3.6
+ vue-router:
+ specifier: ^4.2.5
+ version: 4.2.5(vue@3.3.6)
devDependencies:
'@vitejs/plugin-vue':
@@ -288,6 +300,10 @@ packages:
'@vue/compiler-dom': 3.3.6
'@vue/shared': 3.3.6
+ /@vue/devtools-api@6.5.1:
+ resolution: {integrity: sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==}
+ dev: false
+
/@vue/reactivity-transform@3.3.6:
resolution: {integrity: sha512-RlJl4dHfeO7EuzU1iJOsrlqWyJfHTkJbvYz/IOJWqu8dlCNWtxWX377WI0VsbAgBizjwD+3ZjdnvSyyFW1YVng==}
dependencies:
@@ -371,6 +387,21 @@ packages:
dev: true
optional: true
+ /graphql-tag@2.12.6(graphql@16.8.1):
+ resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
+ dependencies:
+ graphql: 16.8.1
+ tslib: 2.6.2
+ dev: false
+
+ /graphql@16.8.1:
+ resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==}
+ engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
+ dev: false
+
/magic-string@0.30.5:
resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==}
engines: {node: '>=12'}
@@ -409,6 +440,20 @@ packages:
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
engines: {node: '>=4'}
+ /tslib@2.6.2:
+ resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
+ dev: false
+
+ /villus@3.2.0(graphql@16.8.1)(vue@3.3.6):
+ resolution: {integrity: sha512-kb4Dv6Uvu7FSqfVnXTFb7I+VDv9fzFG2Emqu1eu9acY/Y3xM8xqy/I8w/HexNYDkofx5fGIgWk9nvfEWROtlGw==}
+ peerDependencies:
+ graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
+ vue: ^3.0.0 || ^2.7.0
+ dependencies:
+ graphql: 16.8.1
+ vue: 3.3.6
+ dev: false
+
/vite@4.5.0:
resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==}
engines: {node: ^14.18.0 || >=16.0.0}
@@ -444,6 +489,15 @@ packages:
fsevents: 2.3.3
dev: true
+ /vue-router@4.2.5(vue@3.3.6):
+ resolution: {integrity: sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==}
+ peerDependencies:
+ vue: ^3.2.0
+ dependencies:
+ '@vue/devtools-api': 6.5.1
+ vue: 3.3.6
+ dev: false
+
/vue@3.3.6:
resolution: {integrity: sha512-jJIDETeWJnoY+gfn4ZtMPMS5KtbP4ax+CT4dcQFhTnWEk8xMupFyQ0JxL28nvT/M4+p4a0ptxaV2WY0LiIxvRg==}
peerDependencies:
diff --git a/frontend/public/vite.svg b/frontend/public/favicon.svg
similarity index 100%
rename from frontend/public/vite.svg
rename to frontend/public/favicon.svg
diff --git a/frontend/src/.d.ts b/frontend/src/.d.ts
new file mode 100644
index 0000000..34dfa67
--- /dev/null
+++ b/frontend/src/.d.ts
@@ -0,0 +1 @@
+declare module 'vue/dist/vue.esm-bundler.js';
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index 341dbf0..436641e 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -1,30 +1,21 @@
-
-
+
-
-
+ Home |
+ About
+
diff --git a/frontend/src/components/HelloWorld.vue b/frontend/src/components/HelloWorld.vue
index f5e4f53..97cd48c 100644
--- a/frontend/src/components/HelloWorld.vue
+++ b/frontend/src/components/HelloWorld.vue
@@ -1,40 +1,43 @@
- {{ msg }}
+ {{ msg }}
-
-
-
- Edit
- components/HelloWorld.vue
to test HMR
-
-
+
+
+
+ Edit
+ components/HelloWorld.vue
to test HMR
+
+
-
- Check out
- create-vue, the official Vue + Vite starter
-
-
- Install
- Volar
- in your IDE for a better DX
-
- Click on the Vite and Vue logos to learn more
+
+ Check out
+ create-vue, the official Vue + Vite starter
+
+
+ Install
+ Volar
+ in your IDE for a better DX
+
+ Go to vitejs.dev or
+ vuejs.org to learn more
diff --git a/frontend/src/components/Users.vue b/frontend/src/components/Users.vue
new file mode 100644
index 0000000..749ce83
--- /dev/null
+++ b/frontend/src/components/Users.vue
@@ -0,0 +1,38 @@
+
+
+
See GraphQl in action:
+
+ - {{ user.userName }}
+
+
+
+
+
+
+
+
diff --git a/frontend/src/main.js b/frontend/src/main.js
index 2425c0f..e130536 100644
--- a/frontend/src/main.js
+++ b/frontend/src/main.js
@@ -1,5 +1,26 @@
-import { createApp } from 'vue'
+import { createApp } from 'vue/dist/vue.esm-bundler.js'
+import { createClient } from 'villus'
+import { createRouter, createWebHistory } from 'vue-router'
import './style.css'
import App from './App.vue'
+import Home from './views/Home.vue'
+import About from './views/About.vue'
-createApp(App).mount('#app')
+const NotFound = { template: 'Sorry, page not found (404)
' }
+
+const routes = [
+ { path: '/', name: 'Home', component: Home },
+ { path: '/about', name: 'About', component: About },
+ { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound }
+]
+
+const router = createRouter({
+ history: createWebHistory(),
+ routes
+})
+
+const villusClient = createClient({
+ url: '/api'
+})
+
+createApp(App).use(router).use(villusClient).mount('#app')
diff --git a/frontend/src/style.css b/frontend/src/style.css
index 84a0050..d737880 100644
--- a/frontend/src/style.css
+++ b/frontend/src/style.css
@@ -1,89 +1,95 @@
:root {
- font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
- line-height: 1.5;
- font-weight: 400;
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
- color-scheme: light dark;
- color: rgba(255, 255, 255, 0.87);
- background-color: #242424;
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- -webkit-text-size-adjust: 100%;
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-text-size-adjust: 100%;
}
a {
- font-weight: 500;
- color: #646cff;
- text-decoration: inherit;
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
}
+
a:hover {
- color: #535bf2;
+ color: #535bf2;
}
a {
- font-weight: 500;
- color: #646cff;
- text-decoration: inherit;
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
}
+
a:hover {
- color: #535bf2;
+ color: #535bf2;
}
body {
- margin: 0;
- display: flex;
- place-items: center;
- min-width: 320px;
- min-height: 100vh;
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
}
h1 {
- font-size: 3.2em;
- line-height: 1.1;
+ font-size: 3.2em;
+ line-height: 1.1;
}
button {
- border-radius: 8px;
- border: 1px solid transparent;
- padding: 0.6em 1.2em;
- font-size: 1em;
- font-weight: 500;
- font-family: inherit;
- background-color: #1a1a1a;
- cursor: pointer;
- transition: border-color 0.25s;
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
}
+
button:hover {
- border-color: #646cff;
+ border-color: #646cff;
}
+
button:focus,
button:focus-visible {
- outline: 4px auto -webkit-focus-ring-color;
+ outline: 4px auto -webkit-focus-ring-color;
}
.card {
- padding: 2em;
+ padding: 2em;
}
#app {
- max-width: 1280px;
- margin: 0 auto;
- padding: 2rem;
- text-align: center;
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
}
@media (prefers-color-scheme: light) {
- :root {
- color: #213547;
- background-color: #ffffff;
- }
- a:hover {
- color: #747bff;
- }
- button {
- background-color: #f9f9f9;
- }
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+
+ a:hover {
+ color: #747bff;
+ }
+
+ button {
+ background-color: #f9f9f9;
+ }
}
diff --git a/frontend/src/views/About.vue b/frontend/src/views/About.vue
new file mode 100644
index 0000000..f0ecbe0
--- /dev/null
+++ b/frontend/src/views/About.vue
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/frontend/src/views/Home.vue b/frontend/src/views/Home.vue
new file mode 100644
index 0000000..d223d67
--- /dev/null
+++ b/frontend/src/views/Home.vue
@@ -0,0 +1,8 @@
+
+
+
+ Welcome, this is YetAnotherTodoList
+
+
diff --git a/server/handleDevTools.go b/server/handleDevTools.go
index ee00bf1..27eb79b 100644
--- a/server/handleDevTools.go
+++ b/server/handleDevTools.go
@@ -20,11 +20,11 @@ along with this program. If not, see .
package server
import (
- "net/http"
-
"github.com/99designs/gqlgen/graphql/playground"
+ "somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/globals"
)
-func handleDevTools() {
- http.Handle("/playground", playground.Handler("GraphQL playground", "/api"))
+func handleDevTools(port int) {
+ mux.Handle("/playground", playground.Handler("GraphQL playground", "/api"))
+ globals.Logger.Printf("connect to http://localhost:%v/ for GraphQL playground", port)
}
diff --git a/server/handleDevTools.mock.go b/server/handleDevTools.mock.go
index c31422d..7548ddf 100644
--- a/server/handleDevTools.mock.go
+++ b/server/handleDevTools.mock.go
@@ -19,5 +19,5 @@ along with this program. If not, see .
*/
package server
-func handleDevTools() {
+func handleDevTools(_ int) {
}
diff --git a/server/handleFrontend.go b/server/handleFrontend.go
index 8f1efc6..756d04a 100644
--- a/server/handleFrontend.go
+++ b/server/handleFrontend.go
@@ -34,7 +34,21 @@ func handleFrontend() {
if err != nil {
log.Fatalln(err)
}
-
frontendFS := http.FileServer(http.FS(stripped))
- http.Handle("/", frontendFS)
+ mux.Handle("/assets/", frontendFS)
+ mux.HandleFunc("/", indexHandler)
+ // TODO: redirect from vue to 404 page (on go/proxy server)
+}
+
+// Following Nathan Tsao's implementation on https://betterprogramming.pub/how-to-serve-a-single-page-application-using-go-4b9a38d92987
+func indexHandler(w http.ResponseWriter, r *http.Request) {
+ // TODO: add map with path:type
+ if r.URL.Path == "/vite.svg" {
+ rawFile, _ := frontend.ReadFile("dist/vite.svg")
+ w.Header().Add("Content-Type", "image/svg+xml")
+ w.Write(rawFile)
+ return
+ }
+ rawFile, _ := frontend.ReadFile("dist/index.html")
+ w.Write(rawFile)
}
diff --git a/server/main.go b/server/main.go
index d7c096a..9709244 100644
--- a/server/main.go
+++ b/server/main.go
@@ -26,16 +26,20 @@ import (
"somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph"
)
-func StartServer(port int) {
- handleDevTools() // controlled by 'dev' tag
- handleFrontend() // controlled by 'headless' tag
+var mux *http.ServeMux
- http.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) {
+func StartServer(port int) {
+ mux = http.NewServeMux()
+
+ handleDevTools(port) // controlled by 'dev' tag
+ handleFrontend() // controlled by 'headless' tag
+
+ mux.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%s %s", globals.Version, globals.CommitHash)
})
srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}}))
- http.Handle("/api", srv)
- globals.Logger.Printf("connect to http://localhost:%v/ for GraphQL playground", port)
- globals.Logger.Fatal(http.ListenAndServe(":"+strconv.FormatInt(int64(port), 10), nil))
+ mux.Handle("/api", srv)
+
+ globals.Logger.Fatal(http.ListenAndServe(":"+strconv.FormatInt(int64(port), 10), mux))
}