Printer Card Alpha

This commit is contained in:
Douglas Barone 2023-06-29 10:07:23 -04:00
parent aa5076a157
commit 5502c84330
12 changed files with 140 additions and 60 deletions

View File

@ -24,7 +24,13 @@ class PrinterController {
shortName: String(campus) shortName: String(campus)
} }
}, },
include: { network: true } include: {
network: true,
status: {
orderBy: { timestamp: 'desc' },
take: 1
}
}
}) })
return res.json(printers) return res.json(printers)
@ -32,7 +38,7 @@ class PrinterController {
static async show(req: Request, res: Response) { static async show(req: Request, res: Response) {
const { id } = req.params const { id } = req.params
const { take = 64, days = 60 } = req.query const { take = 32, days = 60 } = req.query
const gte = new Date(Date.now() - 1000 * 60 * 60 * 24 * Number(days)) const gte = new Date(Date.now() - 1000 * 60 * 60 * 24 * Number(days))

View File

@ -14,12 +14,11 @@ import PrinterDiscoveryRouter from './controllers/PrinterDiscoveryController.js'
export const app = express() export const app = express()
app.use(cors()) app.use(cors())
app.use(populateUserMiddleware)
app.use(loggerMiddleware) app.use(loggerMiddleware)
app.use('/api', bodyParser.json()) app.use('/api', bodyParser.json())
app.use('/api', populateUserMiddleware)
app.use('/api/login', LoginRouter) app.use('/api/login', LoginRouter)
app.use('/api/printer', PrinterRouter) app.use('/api/printer', PrinterRouter)
app.use('/api/printer-status', PrinterStatusRouter) app.use('/api/printer-status', PrinterStatusRouter)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 177 KiB

View File

@ -5,9 +5,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useAppStore } from "./store/app"; import { useAppStore } from './store/appStore'
const appStore = useAppStore(); const appStore = useAppStore()
appStore.fetchMe(); appStore.fetchMe()
</script> </script>
./store/appStore

View File

@ -1,18 +1,95 @@
<template> <template>
<v-card> <v-card variant="outlined" class="printer-card">
<v-row> <div class="d-flex align-center">
<v-col :cols="4"> <div class="flex-shrink-1 fill-height" style="width: 128px">
<printer-img :model="printer.model" /> <printer-img class="pa-2" :model="printer.model" />
</v-col> </div>
<v-col :cols="6">{{ printer.serialNumber }}</v-col> <div>
</v-row> <v-list density="compact">
<v-list-item>
<template v-slot:prepend>
<v-icon icon="mdi-printer"></v-icon>
</template>
<v-list-item-title>{{ printer.serialNumber }}</v-list-item-title>
<v-list-item-subtitle>{{ printer.model }}</v-list-item-subtitle>
</v-list-item>
<v-list-item>
<template v-slot:prepend>
<v-icon icon="mdi-map"></v-icon>
</template>
<v-list-item-title>
{{ printer.location || '-' }}
</v-list-item-title>
<v-list-item-subtitle>
{{ printer.ip }} ({{ printer.network.name }})
</v-list-item-subtitle>
</v-list-item>
<v-list-item>
<template v-slot:prepend>
<v-icon icon="mdi-clock"></v-icon>
</template>
<v-list-item-title>
{{ new Date(printer.updatedAt).toLocaleString() }}
</v-list-item-title>
<v-list-item-subtitle>Última atualização</v-list-item-subtitle>
</v-list-item>
</v-list>
</div>
<div class="flex-grow-1">
<v-list density="compact">
<v-list-subheader>Toner</v-list-subheader>
<v-list-item>
<v-list-item-title>
<v-progress-linear
:title="`${printer.status[0].tonerBlackLevel}%`"
class="mb-1"
height="5"
:model-value="printer.status[0].tonerBlackLevel"
/>
</v-list-item-title>
<v-list-item-subtitle>
{{ printer.blackTonerModel }}
<v-chip
size="x-small"
title="Nível do toner"
variant="tonal"
:color="
printer.status[0].tonerBlackLevel < 10
? 'error'
: printer.status[0].tonerBlackLevel < 20
? 'warning'
: ''
"
>
{{ printer.status[0].tonerBlackLevel }}%
</v-chip>
</v-list-item-subtitle>
</v-list-item>
<v-list-item>
<v-list-item-title>
{{ printer.location || '-' }}
</v-list-item-title>
<v-list-item-subtitle>
{{ printer.ip }} ({{ printer.network.name }})
</v-list-item-subtitle>
</v-list-item>
</v-list>
</div>
</div>
</v-card> </v-card>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import PrinterImg from '@/components/PrinterImg.vue' import PrinterImg from '@/components/PrinterImg.vue'
import { Printer } from '@prisma/client'
defineProps<{ defineProps<{
printer: Printer printer: any
}>() }>()
</script> </script>
<style scoped>
.printer-card {
border-color: #efefef;
}
</style>

View File

@ -1,16 +1,16 @@
<template> <template>
<v-img :height="size" :src="`/img/${model}.png`" /> <v-img class="ma-auto" :src="`/img/${model}.png`" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
defineProps({ defineProps({
model: { model: {
type: String, type: String,
required: true, required: true
}, },
size: { size: {
type: Number, type: Number,
default: 128, default: 128
}, }
}) })
</script> </script>

View File

@ -44,7 +44,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useAppStore } from '@/store/app' import { useAppStore } from '@/store/appStore'
import { removeJwtToken } from '@/auth' import { removeJwtToken } from '@/auth'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
@ -59,3 +59,4 @@ function logout() {
router.push({ name: 'Login' }) router.push({ name: 'Login' })
} }
</script> </script>
@/store/appStore

View File

@ -2,14 +2,14 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { api } from '@/api' import { api } from '@/api'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { Printer, User } from '@prisma/client' import type { Printer, User, Network } from '@prisma/client'
const router = useRouter() const router = useRouter()
export const useAppStore = defineStore('app', { export const useAppStore = defineStore('app', {
state: () => ({ state: () => ({
me: null as User | null, me: null as User | null,
printers: [] as Printer[], printers: [] as any[],
printerFilter: '', printerFilter: '',
onlyMyCampus: true, onlyMyCampus: true,
loadingPrinters: false loadingPrinters: false
@ -19,7 +19,7 @@ export const useAppStore = defineStore('app', {
async fetchPrinters() { async fetchPrinters() {
this.loadingPrinters = true this.loadingPrinters = true
try { try {
this.printers = await api<Printer[]>( this.printers = await api<any[]>(
`printer?${new URLSearchParams({ `printer?${new URLSearchParams({
campus: this.onlyMyCampus ? this.me?.campus || '' : '' campus: this.onlyMyCampus ? this.me?.campus || '' : ''
})}`, })}`,

View File

@ -1,13 +1,7 @@
<template> <template>
<v-container fluid> <v-container fluid>
<v-row> <v-row>
<v-col <v-col cols="12" v-for="printer in appStore.printers" :key="printer.id">
cols="12"
md="6"
lg="4"
v-for="printer in appStore.printers"
:key="printer.id"
>
<printer-card :printer="printer" /> <printer-card :printer="printer" />
</v-col> </v-col>
</v-row> </v-row>
@ -16,7 +10,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import PrinterCard from '@/components/PrinterCard.vue' import PrinterCard from '@/components/PrinterCard.vue'
import { useAppStore } from '@/store/app' import { useAppStore } from '@/store/appStore'
import { onMounted } from 'vue' import { onMounted } from 'vue'
@ -27,3 +21,4 @@ onMounted(async () => {
await appStore.fetchPrinters() await appStore.fetchPrinters()
}) })
</script> </script>
@/store/appStore

View File

@ -60,55 +60,56 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive } from "vue"; import { ref, reactive } from 'vue'
import { api } from "@/api"; import { api } from '@/api'
import { getJwtToken, saveJwtToken } from "@/auth"; import { getJwtToken, saveJwtToken } from '@/auth'
import { useRouter } from "vue-router"; import { useRouter } from 'vue-router'
import { useAppStore } from "@/store/app"; import { useAppStore } from '@/store/app'
const router = useRouter(); const router = useRouter()
const token = getJwtToken(); const token = getJwtToken()
const { fetchMe } = useAppStore(); const { fetchMe } = useAppStore()
if (token) { if (token) {
fetchMe(); fetchMe()
router.replace({ name: "Home" }); router.replace({ name: 'Home' })
} }
const username = ref<string>(""); const username = ref<string>('')
const password = ref<string>(""); const password = ref<string>('')
const valid = ref(false); const valid = ref(false)
const errors = reactive<string[]>([]); const errors = reactive<string[]>([])
const loading = ref(false); const loading = ref(false)
async function login() { async function login() {
errors.splice(0, errors.length); errors.splice(0, errors.length)
try { try {
loading.value = true; loading.value = true
const data = await api<{ token: string }>("login", { const data = await api<{ token: string }>('login', {
method: "POST", method: 'POST',
body: JSON.stringify({ body: JSON.stringify({
username: username.value, username: username.value,
password: password.value, password: password.value
}), })
}); })
const token = data.token; const token = data.token
saveJwtToken(token); saveJwtToken(token)
await fetchMe(); await fetchMe()
router.push({ name: "Home" }); router.push({ name: 'Home' })
} catch (error: any) { } catch (error: any) {
errors.push(error.message); errors.push(error.message)
} finally { } finally {
loading.value = false; loading.value = false
} }
} }
</script> </script>
@/store/appStore