Add cards, use oboe to stream JSON, handle connection failures
This commit is contained in:
parent
2f45d49ac0
commit
d6127e8dfa
|
@ -1,2 +1,3 @@
|
||||||
.vscode
|
.vscode
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.venv
|
||||||
|
|
|
@ -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>
|
|
@ -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();
|
const runtimeConfig = useRuntimeConfig();
|
||||||
return await axios(`${runtimeConfig.public.apiBaseUrl}${path}`, {
|
return oboe(`${runtimeConfig.public.apiBaseUrl}${path}`).node({ 'items.*': callback }).fail(_ => onFail()).done(_ => onSuccess());
|
||||||
...options,
|
|
||||||
headers: options.headers,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,12 @@
|
||||||
"postinstall": "nuxt prepare"
|
"postinstall": "nuxt prepare"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/oboe": "^2.1.4",
|
||||||
"@vueuse/nuxt": "^10.9.0",
|
"@vueuse/nuxt": "^10.9.0",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"nuxt": "^3.11.2",
|
"nuxt": "^3.11.2",
|
||||||
|
"oboe": "^2.1.7",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
"tailwindcss": "^3.4.3",
|
"tailwindcss": "^3.4.3",
|
||||||
"vue": "^3.4.27",
|
"vue": "^3.4.27",
|
||||||
|
|
|
@ -1,34 +1,68 @@
|
||||||
<template>
|
<template>
|
||||||
<NuxtLayout name="ui">
|
<NuxtLayout name="ui">
|
||||||
<h1 class="px-10 py-10">TEST CASE - Welkom to the page!</h1>
|
<header :class="errorClasses">
|
||||||
<div class="relative px-10 py-10 flex items-center justify-center">
|
Connection failed. <button @click="update">Click here to retry</button>.
|
||||||
<div class="flex flex-col gap-4">
|
</header>
|
||||||
<button
|
<main class="grid">
|
||||||
@click="helloWorld"
|
<Card v-for="item in items" :title="item.title" :description="item.description" :type="item.type"/>
|
||||||
class="bg-red-300 rounded-md px-2 hover:bg-slate-300"
|
</main>
|
||||||
>
|
|
||||||
Click me!
|
|
||||||
</button>
|
|
||||||
<div class="bg-slate-600 rounded-md text-md text-white px-2">
|
<div class="bg-slate-600 rounded-md text-md text-white px-2">
|
||||||
{{ sync }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</NuxtLayout>
|
</NuxtLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const sync: Ref<string> = ref("");
|
import Card from '../components/Card.vue'
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
|
||||||
function reset() {
|
onMounted(_ => update())
|
||||||
sync.value = "";
|
|
||||||
|
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() {
|
function failure() {
|
||||||
reset();
|
errorClasses.value = "error"
|
||||||
const res = await useAxios(`/hello_world`, {
|
console.log("aaaaaa")
|
||||||
method: "GET",
|
}
|
||||||
});
|
|
||||||
sync.value = res.data;
|
async function update() {
|
||||||
|
errorClasses.value = "error hidden"
|
||||||
|
await streamRequest("/hello_world/json", updateItem, failure, update);
|
||||||
}
|
}
|
||||||
</script>
|
</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>
|
|
@ -1299,6 +1299,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types "~5.26.4"
|
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":
|
"@types/resolve@1.20.2":
|
||||||
version "1.20.2"
|
version "1.20.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975"
|
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"
|
statuses "2.0.1"
|
||||||
toidentifier "1.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:
|
http-proxy-agent@^7.0.0:
|
||||||
version "7.0.2"
|
version "7.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e"
|
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"
|
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
|
||||||
integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
|
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:
|
ofetch@^1.3.3, ofetch@^1.3.4:
|
||||||
version "1.3.4"
|
version "1.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.4.tgz#7ea65ced3c592ec2b9906975ae3fe1d26a56f635"
|
resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.4.tgz#7ea65ced3c592ec2b9906975ae3fe1d26a56f635"
|
||||||
|
@ -5113,7 +5132,16 @@ streamx@^2.15.0:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
bare-events "^2.2.0"
|
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"
|
version "4.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
|
@ -5145,7 +5173,14 @@ string_decoder@~1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "~5.1.0"
|
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"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
|
@ -5821,7 +5856,16 @@ wide-align@^1.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
string-width "^1.0.2 || 2 || 3 || 4"
|
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"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||||
|
|
Loading…
Reference in New Issue