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)
}
},
include: { network: true }
include: {
network: true,
status: {
orderBy: { timestamp: 'desc' },
take: 1
}
}
})
return res.json(printers)
@ -32,7 +38,7 @@ class PrinterController {
static async show(req: Request, res: Response) {
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))

View File

@ -14,12 +14,11 @@ import PrinterDiscoveryRouter from './controllers/PrinterDiscoveryController.js'
export const app = express()
app.use(cors())
app.use(populateUserMiddleware)
app.use(loggerMiddleware)
app.use('/api', bodyParser.json())
app.use('/api', populateUserMiddleware)
app.use('/api/login', LoginRouter)
app.use('/api/printer', PrinterRouter)
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>
<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>
./store/appStore

View File

@ -1,18 +1,95 @@
<template>
<v-card>
<v-row>
<v-col :cols="4">
<printer-img :model="printer.model" />
</v-col>
<v-col :cols="6">{{ printer.serialNumber }}</v-col>
</v-row>
<v-card variant="outlined" class="printer-card">
<div class="d-flex align-center">
<div class="flex-shrink-1 fill-height" style="width: 128px">
<printer-img class="pa-2" :model="printer.model" />
</div>
<div>
<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>
</template>
<script lang="ts" setup>
import PrinterImg from '@/components/PrinterImg.vue'
import { Printer } from '@prisma/client'
defineProps<{
printer: Printer
printer: any
}>()
</script>
<style scoped>
.printer-card {
border-color: #efefef;
}
</style>

View File

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

View File

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

View File

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

View File

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

View File

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