Add cards, use oboe to stream JSON, handle connection failures

This commit is contained in:
user 2024-10-31 16:41:45 +01:00
parent 2f45d49ac0
commit d6127e8dfa
6 changed files with 149 additions and 30 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
.vscode
.DS_Store
.venv

View File

@ -0,0 +1,41 @@
<script setup>
import { ref, watch } from 'vue'
const type = ref();
const card = ref();
defineProps(['title', 'description', 'type'])
watch(type, (prev, current) => {
card.style.toggleClass('type-a', current.match(/a/i))
card.style.toggleClass('type-b', current.match(/b/i))
})
</script>
<template>
<section ref="card" class="card">
<footer>{{ type }}</footer>
<header><h1>{{ title }}</h1></header>
<main>{{ description }}</main>
</section>
</template>
<style>
.card {
background-color: lightgrey;
height: 100%;
width: 100%;
}
.card.type-a {
background-color: red;
}
.card.type-b {
background-color: orange;
}
.card footer {
float: right;
}
.card h1 {
size: 1em;
}
</style>

View File

@ -1,9 +1,6 @@
import axios from "axios";
import oboe from "oboe";
export async function useAxios(path: string, options: any) {
export async function streamRequest(path: string, callback: oboe.CallbackSignature, onFail: Function, onSuccess: Function) {
const runtimeConfig = useRuntimeConfig();
return await axios(`${runtimeConfig.public.apiBaseUrl}${path}`, {
...options,
headers: options.headers,
});
return oboe(`${runtimeConfig.public.apiBaseUrl}${path}`).node({ 'items.*': callback }).fail(_ => onFail()).done(_ => onSuccess());
}

View File

@ -10,10 +10,12 @@
"postinstall": "nuxt prepare"
},
"dependencies": {
"@types/oboe": "^2.1.4",
"@vueuse/nuxt": "^10.9.0",
"autoprefixer": "^10.4.19",
"axios": "^1.7.2",
"nuxt": "^3.11.2",
"oboe": "^2.1.7",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.3",
"vue": "^3.4.27",

View File

@ -1,34 +1,68 @@
<template>
<NuxtLayout name="ui">
<h1 class="px-10 py-10">TEST CASE - Welkom to the page!</h1>
<div class="relative px-10 py-10 flex items-center justify-center">
<div class="flex flex-col gap-4">
<button
@click="helloWorld"
class="bg-red-300 rounded-md px-2 hover:bg-slate-300"
>
Click me!
</button>
<header :class="errorClasses">
Connection failed. <button @click="update">Click here to retry</button>.
</header>
<main class="grid">
<Card v-for="item in items" :title="item.title" :description="item.description" :type="item.type"/>
</main>
<div class="bg-slate-600 rounded-md text-md text-white px-2">
{{ sync }}
</div>
</div>
</div>
</NuxtLayout>
</template>
<script setup lang="ts">
const sync: Ref<string> = ref("");
import Card from '../components/Card.vue'
import { ref, onMounted } from 'vue'
function reset() {
sync.value = "";
onMounted(_ => update())
const items = ref([...new Array(9)].map((_, i) => ({
title: `Item ${i}`,
description: "",
type: "?"
}))
)
const errorClasses = ref("error hidden")
function updateItem(item) {
items.value.forEach(n => {
if (n.title == item.title) {
if (item.description)
n.description = item.description;
if (item.type)
n.type = item.type;
}
})
}
async function helloWorld() {
reset();
const res = await useAxios(`/hello_world`, {
method: "GET",
});
sync.value = res.data;
function failure() {
errorClasses.value = "error"
console.log("aaaaaa")
}
async function update() {
errorClasses.value = "error hidden"
await streamRequest("/hello_world/json", updateItem, failure, update);
}
</script>
<style>
.grid {
align-items: center;
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: auto auto auto;
margin: 1em;
gap: 1em;
}
.error {
background-color: red;
}
.hidden {
display: none;
}
</style>

View File

@ -1299,6 +1299,13 @@
dependencies:
undici-types "~5.26.4"
"@types/oboe@^2.1.4":
version "2.1.4"
resolved "https://registry.yarnpkg.com/@types/oboe/-/oboe-2.1.4.tgz#d92c4636d0b7737803e4361e10e8dad488f39634"
integrity sha512-bXt4BXSQy0N/buSIak1o0TjYAk2SAeK1aZV9xKcb+xVGWYP8NcMOFy2T7Um3kIvEcQJzrdgJ8R6fpbRcp/LEww==
dependencies:
"@types/node" "*"
"@types/resolve@1.20.2":
version "1.20.2"
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975"
@ -3042,6 +3049,11 @@ http-errors@2.0.0:
statuses "2.0.1"
toidentifier "1.0.1"
http-https@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b"
integrity sha512-o0PWwVCSp3O0wS6FvNr6xfBCHgt0m1tvPLFOCc2iFDKTRAXhB7m8klDf7ErowFH8POa6dVdGatKU5I1YYwzUyg==
http-proxy-agent@^7.0.0:
version "7.0.2"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e"
@ -4139,6 +4151,13 @@ object-hash@^3.0.0:
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
oboe@^2.1.7:
version "2.1.7"
resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.7.tgz#14cb69c750757a964c760383e094887822a32947"
integrity sha512-Y2oCMU2xgITORaNvIDCvUyn2ZG/5NI19lLjMFThgYzCH+GA/fgYvVcwxAqnZPiMiUrPq64jLzCkBXqKSu/R6MA==
dependencies:
http-https "^1.0.0"
ofetch@^1.3.3, ofetch@^1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.4.tgz#7ea65ced3c592ec2b9906975ae3fe1d26a56f635"
@ -5113,7 +5132,16 @@ streamx@^2.15.0:
optionalDependencies:
bare-events "^2.2.0"
"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -5145,7 +5173,14 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@ -5821,7 +5856,16 @@ wide-align@^1.1.2:
dependencies:
string-width "^1.0.2 || 2 || 3 || 4"
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==