Skip to content

Commit

Permalink
Use suspense for loading state (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
fauxpark authored Aug 25, 2024
1 parent 6dc8cc7 commit aeb74b4
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 173 deletions.
184 changes: 11 additions & 173 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,151 +1,23 @@
<template>
<h1>QMK API Keyboard Status</h1>
<div v-if="loading" id="loading">
<ProgressBar :progress="loadProgress" />
</div>
<div v-else>
<input v-model="filter" id="filter" placeholder="filter keyboards" />
<h5>Loaded in {{ loadTime }} seconds</h5>
<BuildList :list="failingKeyboards" :filter="filter" @show-error-pane="showErrors">
Builds Failing
</BuildList>
<BuildList :list="warningKeyboards" :filter="filter" @show-error-pane="showErrors">
Builds Warning
</BuildList>
<BuildList :list="passingKeyboards" :filter="filter" @show-error-pane="showErrors">
Builds Passing
</BuildList>
<ErrorPane
:visible="showErrorPane"
:error-log="errorLog"
:loading="errorLogLoading"
@backdrop-clicked="hideErrors"
/>
</div>
<Suspense>
<BuildOverview @progress="(p) => (loadProgress = p)" />

<template #fallback>
<div id="loading">
<ProgressBar :progress="loadProgress" />
</div>
</template>
</Suspense>
</template>

<script setup>
import { onMounted, ref } from 'vue'
import { ref } from 'vue'
import axios from 'axios'
import reduce from 'lodash/reduce'
import BuildList from '@/components/BuildList.vue'
import ErrorPane from '@/components/ErrorPane.vue'
import BuildOverview from '@/components/BuildOverview.vue'
import ProgressBar from '@/components/ProgressBar.vue'
let buildLog = {}
const loading = ref(true)
const loadTime = ref('')
const loadProgress = ref(0)
const filter = ref('')
const passingKeyboards = ref([])
const warningKeyboards = ref([])
const failingKeyboards = ref([])
const errorLog = ref('')
const errorLogLoading = ref(false)
const showErrorPane = ref(false)
onMounted(() => {
loadBuildSummary()
})
async function loadBuildSummary() {
const start = performance.now()
try {
const { status, data } = await axios.get(
`${import.meta.env.VITE_QMK_API_BASEURL}/v1/keyboards/build_summary`,
{
onDownloadProgress: (e) => {
loadProgress.value = Math.floor((e.loaded / e.total) * 100)
}
}
)
if (status === 200) {
buildLog = data
binKeyboards()
}
} catch (e) {
console.log(e.message)
}
loading.value = false
loadTime.value = ((performance.now() - start) / 1000).toFixed(2)
}
async function loadBuildLog(keyboard) {
errorLogLoading.value = true
try {
const { status, statusText, data } = await axios.get(
`${import.meta.env.VITE_QMK_API_BASEURL}/v1/keyboards/${keyboard}/build_log`
)
if (status === 200) {
buildLog[keyboard].message = data.message
errorLog.value = data.message
} else {
buildLog[keyboard].message = `ERROR ${status}: ${statusText}`
}
} catch (e) {
buildLog[keyboard].message = `ERROR: ${e.message}`
}
errorLogLoading.value = false
errorLog.value = buildLog[keyboard].message
}
function showErrors(key) {
if (!('message' in buildLog[key])) {
loadBuildLog(key)
} else {
errorLog.value = buildLog[key].message
}
showErrorPane.value = true
}
function hideErrors() {
showErrorPane.value = false
}
function compareKeyboardNames(k1, k2) {
return k1.key < k2.key ? -1 : k1.key > k2.key ? 1 : 0
}
function binKeyboards() {
let obj = reduce(
buildLog,
(acc, value, key) => {
let item = {
passed: value.works,
warnings: value.warnings,
key: key,
lastTested: new Date(value.last_tested * 1000)
}
if (item.passed) {
if (item.warnings) {
acc.warn.push(item)
} else {
acc.good.push(item)
}
} else {
acc.bad.push(item)
}
return acc
},
{ good: [], warn: [], bad: [] }
)
obj.good.sort(compareKeyboardNames)
obj.warn.sort(compareKeyboardNames)
obj.bad.sort(compareKeyboardNames)
passingKeyboards.value = obj.good
warningKeyboards.value = obj.warn
failingKeyboards.value = obj.bad
}
</script>

<style>
Expand All @@ -162,23 +34,6 @@ body {
margin-top: 60px;
}
#filter {
padding: 12px;
width: 20%;
font-size: 1.1rem;
color: #2c3e50;
background: #eee;
border: none;
border-radius: 8px;
}
#filter:hover {
background: #ddd;
}
#filter:focus {
outline: none;
background: #d0d0d0;
}
#loading {
margin-top: 1em;
display: flex;
Expand All @@ -187,27 +42,10 @@ body {
gap: 32px;
}
@media (max-width: 640px) {
#filter {
width: 80%;
}
}
@media (prefers-color-scheme: dark) {
body {
background: #202020;
color: #ced9e4;
}
#filter {
background: #1c1c1c;
color: #ced9e4;
}
#filter:hover {
background: #2c2c2c;
}
#filter:focus {
background: #303030;
}
}
</style>
177 changes: 177 additions & 0 deletions src/components/BuildOverview.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<template>
<input v-model="filter" id="filter" placeholder="filter keyboards" />
<h5>Loaded in {{ loadTime }} seconds</h5>
<BuildList :list="failingKeyboards" :filter="filter" @show-error-pane="showErrors">
Builds Failing
</BuildList>
<BuildList :list="warningKeyboards" :filter="filter" @show-error-pane="showErrors">
Builds Warning
</BuildList>
<BuildList :list="passingKeyboards" :filter="filter" @show-error-pane="showErrors">
Builds Passing
</BuildList>
<ErrorPane
:visible="showErrorPane"
:error-log="errorLog"
:loading="errorLogLoading"
@backdrop-clicked="hideErrors"
/>
</template>

<script setup>
import { ref } from 'vue'
import axios from 'axios'
import reduce from 'lodash/reduce'
import BuildList from '@/components/BuildList.vue'
import ErrorPane from '@/components/ErrorPane.vue'
const emit = defineEmits(['progress'])
let buildLog = {}
const loadTime = ref('')
const filter = ref('')
const passingKeyboards = ref([])
const warningKeyboards = ref([])
const failingKeyboards = ref([])
const errorLog = ref('')
const errorLogLoading = ref(false)
const showErrorPane = ref(false)
await loadBuildSummary()
async function loadBuildSummary() {
const start = performance.now()
try {
const { status, data } = await axios.get(
`${import.meta.env.VITE_QMK_API_BASEURL}/v1/keyboards/build_summary`,
{
onDownloadProgress: (e) => {
emit('progress', Math.floor((e.loaded / e.total) * 100))
}
}
)
if (status === 200) {
buildLog = data
binKeyboards()
}
} catch (e) {
console.log(e.message)
}
loadTime.value = ((performance.now() - start) / 1000).toFixed(2)
}
async function loadBuildLog(keyboard) {
errorLogLoading.value = true
try {
const { status, statusText, data } = await axios.get(
`${import.meta.env.VITE_QMK_API_BASEURL}/v1/keyboards/${keyboard}/build_log`
)
if (status === 200) {
buildLog[keyboard].message = data.message
errorLog.value = data.message
} else {
buildLog[keyboard].message = `ERROR ${status}: ${statusText}`
}
} catch (e) {
buildLog[keyboard].message = `ERROR: ${e.message}`
}
errorLogLoading.value = false
errorLog.value = buildLog[keyboard].message
}
function showErrors(key) {
if (!('message' in buildLog[key])) {
loadBuildLog(key)
} else {
errorLog.value = buildLog[key].message
}
showErrorPane.value = true
}
function hideErrors() {
showErrorPane.value = false
}
function compareKeyboardNames(k1, k2) {
return k1.key < k2.key ? -1 : k1.key > k2.key ? 1 : 0
}
function binKeyboards() {
let obj = reduce(
buildLog,
(acc, value, key) => {
let item = {
passed: value.works,
warnings: value.warnings,
key: key,
lastTested: new Date(value.last_tested * 1000)
}
if (item.passed) {
if (item.warnings) {
acc.warn.push(item)
} else {
acc.good.push(item)
}
} else {
acc.bad.push(item)
}
return acc
},
{ good: [], warn: [], bad: [] }
)
obj.good.sort(compareKeyboardNames)
obj.warn.sort(compareKeyboardNames)
obj.bad.sort(compareKeyboardNames)
passingKeyboards.value = obj.good
warningKeyboards.value = obj.warn
failingKeyboards.value = obj.bad
}
</script>
<style scoped>
#filter {
padding: 12px;
width: 20%;
font-size: 1.1rem;
color: #2c3e50;
background: #eee;
border: none;
border-radius: 8px;
}
#filter:hover {
background: #ddd;
}
#filter:focus {
outline: none;
background: #d0d0d0;
}
@media (max-width: 640px) {
#filter {
width: 80%;
}
}
@media (prefers-color-scheme: dark) {
#filter {
background: #1c1c1c;
color: #ced9e4;
}
#filter:hover {
background: #2c2c2c;
}
#filter:focus {
background: #303030;
}
}
</style>

0 comments on commit aeb74b4

Please sign in to comment.