Skip to content

Commit

Permalink
Move from lowdb to Primsa
Browse files Browse the repository at this point in the history
  • Loading branch information
misaon committed Jun 22, 2022
1 parent b6b0bc7 commit 4a12b39
Show file tree
Hide file tree
Showing 25 changed files with 753 additions and 169 deletions.
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.nuxt/
node_modules/
server/data/uptime.db
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ dist

# app
.idea
!.gitkeep
server/data/
server/data/migrations
server/data/*.db
server/data/*.db-journal
11 changes: 6 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@ WORKDIR /app
COPY . ./

RUN yarn install \
&& yarn run build

&& sed -i 's/file:.\//file:\/app\/data\//g' server/data/schema.prisma \
&& $(npm bin)/prisma generate \
&& yarn run build \
&& $(npm bin)/prisma migrate dev --name init

FROM node:18.4.0-alpine3.15

ENV NODE_NO_WARNINGS=1

WORKDIR /app

COPY --from=build /app/.output /app/.output

RUN mkdir -p /app/server /app/server/data
COPY --from=build /app/.output ./.output
COPY --from=build /app/data ./data

ENV HOST=0.0.0.0
ENV PORT=80
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ A fast, minimalistic, and powerful self-hosted monitoring tool built on modern t
### 🐳 Docker

```bash
docker run -p 80:80 -v uptime-nuxt:/app/server/data misaon/uptime-nuxt:latest
docker run -p 80:80 -v uptime-nuxt:/app/data misaon/uptime-nuxt:latest
```

Browse to http://localhost:80 after starting.
Expand Down
2 changes: 1 addition & 1 deletion assets/css/tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

@layer components {
.btn {
@apply flex gap-1 items-center rounded bg-gradient-to-r bg-slate-300 dark:from-slate-700 dark:to-slate-600 py-2 px-3 hover:opacity-80;
@apply flex gap-1 items-center rounded bg-gradient-to-r bg-slate-300 dark:from-slate-700 dark:to-slate-600 py-2 px-3 hover:opacity-80 disabled:opacity-50 disabled:cursor-not-allowed;
}

.btn > svg {
Expand Down
125 changes: 125 additions & 0 deletions components/monitoring-row.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<template>
<NuxtLink :to="`/monitoring/${monitoring.id}`" class="flex gap-6 items-center">
<span class="grow py-5 pl-5 font-medium">{{ monitoring.host }}</span>

<div class="w-1/2 h-14">
<canvas ref="chartTotalDuration" />
</div>

<div class="flex items-center pr-5">
<span
class="p-1 text-white rounded-full"
:class="[isRequestOk ? 'bg-lime-600' : 'bg-orange-600 animate-pulse']"
>
<IconOK v-if="isRequestOk" class="w-6 h-auto" />
<IconError v-else class="w-6 h-auto" />
</span>
</div>
</NuxtLink>
</template>

<script lang="ts" setup>
import {
Chart as ChartJS,
Tooltip,
LineController,
LineElement,
LinearScale,
PointElement,
CategoryScale
} from 'chart.js'
import { computed, onMounted, toRefs, ref, watch } from 'vue'
import { useNuxtApp } from '#app'
import IconOK from '~icons/material-symbols/done'
import IconError from '~icons/material-symbols/close'
const properties = defineProps({
monitoring: {
type: Object,
required: true
}
})
const { monitoring } = toRefs(properties)
const { $colorMode } = useNuxtApp()
const chartTotalDuration = ref()
const lastRequest = computed(() => monitoring.value.requests[0])
const isRequestOk = computed(() => lastRequest.value?.statusCode >= 200 && lastRequest.value?.statusCode < 300)
const chartTotalDurationData = computed(() => {
const items = [...monitoring.value.requests].reverse().slice(0, 75)
return {
labels: items.map(request => request.id),
datasets: [{
data: items.map(request => request.totalDuration),
borderWidth: 1,
pointBorderWidth: 0,
tension: 0.2,
borderColor: $colorMode.value === 'light' ? 'rgb(148 163 184)' : 'rgb(148 163 184)'
}]
}
})
let chartJSInstance
onMounted(() => {
ChartJS.register(
Tooltip,
LineController,
LineElement,
LinearScale,
PointElement,
CategoryScale
)
chartJSInstance = new ChartJS(chartTotalDuration.value, {
type: 'line',
data: chartTotalDurationData.value,
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
display: false
},
x: {
display: false
}
},
elements: {
point: {
borderWidth: 0,
backgroundColor: 'rgba(0,0,0,0)'
}
},
plugins: {
legend: {
display: false
},
tooltip: {
yAlign: 'center',
displayColors: false,
callbacks: {
title: () => '',
label: (context: any) => {
return `Total duration ${Math.round(context.raw)} ms`
}
}
}
}
}
})
})
watch(chartTotalDurationData, (value) => {
if (value.labels.length === chartJSInstance.data.labels.length) {
return
}
chartJSInstance.data = chartTotalDurationData.value
chartJSInstance.update()
})
</script>
22 changes: 22 additions & 0 deletions formkit.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { en } from '@formkit/i18n'
import { DefaultConfigOptions } from '@formkit/vue'
import { generateClasses } from '@formkit/themes'

const config: DefaultConfigOptions = {
locales: { en },
locale: 'en',
config: {
classes: generateClasses({
text: {
outer: 'flex flex-col gap-1',
wrapper: 'flex flex-col gap-1',
label: 'font-bold ',
input: 'input w-full',
help: 'text-slate-400 text-sm',
message: 'py-1 px-2 rounded text-white bg-orange-600 inline-block'
}
})
}
}

export default config
3 changes: 2 additions & 1 deletion nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ export default defineNuxtConfig({
ssr: false,
modules: [
'@nuxtjs/tailwindcss',
'@nuxtjs/color-mode'
'@nuxtjs/color-mode',
'@formkit/nuxt'
],
colorMode: {
// eslint-disable-next-line unicorn/no-keyword-prefix
Expand Down
13 changes: 10 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,29 @@
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"lint": "eslint --ext .vue,.ts,.js,.mjs ."
"lint": "eslint --ext .vue,.ts,.js,.mjs .",
"seed": "prisma migrate dev --name init"
},
"devDependencies": {
"@formkit/nuxt": "^1.0.0-beta.8",
"@formkit/themes": "^1.0.0-beta.8",
"@iconify/json": "^2.1.63",
"@nuxtjs/color-mode": "^3.1.4",
"@nuxtjs/eslint-config-typescript": "^10.0.0",
"@nuxtjs/tailwindcss": "^5.1.2",
"@prisma/client": "^3.15.2",
"@tailwindcss/forms": "^0.5.2",
"chart.js": "^3.8.0",
"eslint": "^8.18.0",
"eslint-plugin-tailwindcss": "^3.5.2",
"nuxt": "3.0.0-rc.4",
"prisma": "^3.15.2",
"typescript": "^4.7.4",
"unplugin-icons": "^0.14.5"
},
"dependencies": {
"lowdb": "^3.0.0"
"prisma": {
"seed": "node ./server/data/seed.ts",
"schema": "./server/data/schema.prisma"
},
"packageManager": "yarn@3.2.1"
}
23 changes: 3 additions & 20 deletions pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,7 @@
<template>
<section class="p-3 bg-slate-100 dark:bg-slate-800 rounded-md">
<section class="bg-slate-100 dark:bg-slate-800 rounded-md">
<div class="flex flex-col divide-y-2 dark:divide-slate-700">
<div
v-for="(monitoring, index) in monitoringList"
:key="index"
class="flex items-center p-3"
>
<span class="grow font-medium">{{ monitoring.host }}</span>
<div class="flex items-center">
<span
class="p-1 text-white rounded-full"
:class="{'bg-lime-600': monitoring.status === 'OK', 'bg-orange-600 animate-pulse': monitoring.status === 'ERROR'}"
>
<IconOK v-if="monitoring.status === 'OK'" class="w-6 h-auto" />
<IconError v-else class="w-6 h-auto" />
</span>
</div>
</div>
<MonitoringRow v-for="monitoring in monitoringList" :key="monitoring.id" :monitoring="monitoring" />
<p v-if="monitoringList.length === 0" class="self-center">
The list is empty, please
<NuxtLink to="/monitoring/create">
Expand All @@ -29,12 +14,10 @@

<script lang="ts" setup>
import { useFetch } from '#imports'
import IconOK from '~icons/material-symbols/done'
import IconError from '~icons/material-symbols/close'
const { data: monitoringList, refresh: refreshList } = await useFetch('/api/monitoring')
setInterval(async () => {
await refreshList()
}, 3000)
}, 5000)
</script>
69 changes: 69 additions & 0 deletions pages/monitoring/[id].vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<template>
<div>
<FormKit
v-slot="{ state: { valid } }"
v-model="formData"
type="form"
form-class="flex flex-col gap-3 p-3 bg-slate-100 dark:bg-slate-800 rounded-md"
:actions="false"
@submit="handleFormSubmit"
>
<FormKit
name="host"
label="Host"
placeholder="www.google.com"
validation="required"
help="Specify a valid host for the server you want to monitor."
/>

<div class="flex justify-between">
<button class="btn" type="button" @click="handleRemoveMonitoring">
<IconDelete />
<span>Delete</span>
</button>

<button class="btn" type="submit" :disabled="!valid">
<IconOK />
<span>Save</span>
</button>
</div>
</formkit>
</div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { useFetch, useRouter, useRoute } from '#imports'
import IconOK from '~icons/material-symbols/done'
import IconDelete from '~icons/material-symbols/delete'
const route = useRoute()
const router = useRouter()
const { data: monitoring } = await useFetch(`/api/monitoring/${route.params.id}`, {
method: 'GET'
})
const formData = ref<any>({
host: monitoring.value.host
})
async function handleFormSubmit () {
await useFetch(`/api/monitoring/${route.params.id}`, {
method: 'PUT',
body: {
host: formData.value.host
}
})
await router.push('/')
}
async function handleRemoveMonitoring () {
await useFetch(`/api/monitoring/${route.params.id}`, {
method: 'DELETE'
})
await router.push('/')
}
</script>
Loading

0 comments on commit 4a12b39

Please sign in to comment.