Printer Card Alpha
This commit is contained in:
parent
aa5076a157
commit
5502c84330
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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 |
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 || '' : ''
|
||||||
})}`,
|
})}`,
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user