convert codebase to typescript

This commit is contained in:
2022-12-19 13:53:20 +01:00
parent 1758af4f3d
commit 071d1f9788
20 changed files with 5995 additions and 1192 deletions

View File

@@ -1,17 +0,0 @@
kind: pipeline
type: ssh
name: default
server:
host: nuc.home
user:
from_secret: ssh_username
password:
from_secret: ssh_password
steps:
- name: build
commands:
- cd /home/marco/containers
- docker-compose build sensor-web-v2
- docker-compose up -d sensor-web-v2

View File

@@ -3,9 +3,14 @@ require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = { module.exports = {
root: true, root: true,
extends: ['plugin:vue/vue3-essential', 'eslint:recommended', '@vue/eslint-config-prettier'], extends: [
env: { 'plugin:vue/vue3-essential',
'vue/setup-compiler-macros': true 'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier'
],
parserOptions: {
ecmaVersion: 'latest'
}, },
rules: { rules: {
'vue/multi-word-component-names': 'off' 'vue/multi-word-component-names': 'off'

View File

@@ -1,10 +1,21 @@
# vue-project # vue-ts
This template should help get you started developing with Vue 3 in Vite. This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup ## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.vscode-typescript-vue-plugin). [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Type Support for `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
1. Disable the built-in TypeScript Extension
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
## Customize configuration ## Customize configuration
@@ -22,7 +33,7 @@ npm install
npm run dev npm run dev
``` ```
### Compile and Minify for Production ### Type-Check, Compile and Minify for Production
```sh ```sh
npm run build npm run build

1
env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@@ -11,6 +11,6 @@
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
<script type="module" src="/src/main.js"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>
</html> </html>

6625
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,28 +3,36 @@
"version": "1.0.0", "version": "1.0.0",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "run-p type-check build-only",
"preview": "vite preview --port 5050", "preview": "vite preview",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore" "build-only": "vite build",
"type-check": "vue-tsc --noEmit",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
}, },
"dependencies": { "dependencies": {
"bulma": "^0.9.4", "bulma": "^0.9.4",
"dayjs": "^1.11.1", "dayjs": "^1.11.7",
"dotenv": "^16.0.0", "dotenv": "^16.0.3",
"express": "^4.18.1", "express": "^4.18.2",
"highcharts": "^10.1.0", "highcharts": "^10.3.2",
"mongodb": "^4.5.0", "mongodb": "^4.13.0",
"sass": "^1.53.0", "sass": "^1.57.0",
"vue": "^3.2.37", "vue": "^3.2.45",
"vue-router": "^4.1.2" "vue-router": "^4.1.6"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.1.4", "@rushstack/eslint-patch": "^1.2.0",
"@vitejs/plugin-vue": "^3.0.0", "@types/node": "^18.11.17",
"@vitejs/plugin-vue": "^4.0.0",
"@vue/eslint-config-prettier": "^7.0.0", "@vue/eslint-config-prettier": "^7.0.0",
"eslint": "^8.19.0", "@vue/eslint-config-typescript": "^11.0.2",
"@vue/tsconfig": "^0.1.3",
"eslint": "^8.30.0",
"eslint-plugin-vue": "^9.2.0", "eslint-plugin-vue": "^9.2.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.7.1", "prettier": "^2.7.1",
"vite": "^3.0.0" "typescript": "^4.9.4",
"vite": "^4.0.2",
"vue-tsc": "^1.0.14"
} }
} }

View File

@@ -4,27 +4,28 @@
<div class="chart" id="chart" ref="chart" v-else></div> <div class="chart" id="chart" ref="chart" v-else></div>
</div> </div>
</template> </template>
<script> <script setup lang="ts">
import { ref, watch, toRefs, nextTick, onMounted } from 'vue' import { ref, watch, toRefs, nextTick, onMounted } from 'vue'
import Highcharts from 'highcharts' import * as Highcharts from 'highcharts'
import 'highcharts/css/highcharts.scss' import 'highcharts/css/highcharts.scss'
import Loader from '@/components/Loader.vue' import Loader from '@/components/Loader.vue'
import { capitalizeFirstLetter } from '@/utils/helpers' import { capitalizeFirstLetter } from '@/utils/helpers'
import type { Window } from '@/utils/types'
Highcharts.setOptions({ Highcharts.setOptions({
time: { time: {
timezoneOffset: new Date().getTimezoneOffset() timezoneOffset: new Date().getTimezoneOffset()
} }
}) })
export default {
props: ['window', 'type'], const props = defineProps<{
components: { window: Window | undefined
Loader type: string
}, }>()
setup(props) {
const data = ref([]) const data = ref([])
const loading = ref(false) const loading = ref(false)
const chart = ref(null) const chart = ref<HTMLElement | null>(null)
const { window, type } = toRefs(props) const { window, type } = toRefs(props)
const fetchData = async () => { const fetchData = async () => {
@@ -38,7 +39,9 @@ export default {
const [start, end] = [window.value.getStart(), window.value.getEnd()] const [start, end] = [window.value.getStart(), window.value.getEnd()]
const sample = Math.round((end - start) / 60 / 288) || 1 const sample = Math.round((end - start) / 60 / 288) || 1
const host = import.meta.env.MODE === 'development' ? 'http://localhost:3000' : '' const host = import.meta.env.MODE === 'development' ? 'http://localhost:3000' : ''
const fetchUrl = `${host}/type/${typeApi[type.value]}/startDate/${start}/endDate/${end}/sample/${sample}` const fetchUrl = `${host}/type/${
typeApi[type.value as keyof typeof typeApi]
}/startDate/${start}/endDate/${end}/sample/${sample}`
const response = await fetch(fetchUrl) const response = await fetch(fetchUrl)
loading.value = false loading.value = false
data.value = await response.json() data.value = await response.json()
@@ -47,10 +50,11 @@ export default {
} }
} }
} }
const renderChart = () => { const renderChart = () => {
const chartData = data.value.map(({ date, value }) => ({ x: date, y: value })) const chartData = data.value.map(({ date, value }) => ({ x: date, y: value }))
Highcharts.chart(chart.value, { Highcharts.chart({
chart: { styledMode: true, marginBottom: 25 }, chart: { renderTo: chart.value || '', styledMode: true, marginBottom: 25 },
title: { text: '' }, title: { text: '' },
legend: { enabled: false }, legend: { enabled: false },
plotOptions: { series: { animation: false, marker: { enabled: false } } }, plotOptions: { series: { animation: false, marker: { enabled: false } } },
@@ -74,17 +78,16 @@ export default {
return this.value + suffix return this.value + suffix
} }
}, },
title: { enabled: false }, title: { text: null },
minTickInterval: 0.1 minTickInterval: 0.1
}, },
series: [{ name: capitalizeFirstLetter(type.value), data: chartData }], series: [{ name: capitalizeFirstLetter(type.value), data: chartData, type: 'line' }],
credits: { enabled: false } credits: { enabled: false }
}) })
} }
watch([window, type], ([newWindow, newType], [oldWindow, oldType]) => {
if (newWindow !== oldWindow || newType !== oldType) { watch([window, type], () => {
fetchData() fetchData(), { immediate: true }
}
}) })
onMounted(() => { onMounted(() => {
watch( watch(
@@ -95,12 +98,6 @@ export default {
{ immediate: true } { immediate: true }
) )
}) })
return {
loading,
chart
}
}
}
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@@ -7,7 +7,7 @@
</div> </div>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/style/_variables.scss"; @import '@/style/_variables.scss';
.lds-ring { .lds-ring {
display: inline-block; display: inline-block;
position: relative; position: relative;

View File

@@ -8,53 +8,42 @@
<router-view></router-view> <router-view></router-view>
</div> </div>
</template> </template>
<script> <script setup lang="ts">
import { ref } from 'vue' import { ref } from 'vue'
import { useRouter } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import NavBar from '@/components/NavBar.vue' import NavBar from '@/components/NavBar.vue'
import TimeWindows from '@/components/TimeWindows.vue' import TimeWindows from '@/components/TimeWindows.vue'
import Chart from '@/components/Chart.vue' import Chart from '@/components/Chart.vue'
export default { import { windows } from '@/utils/helpers'
components: { import type { Window } from '@/utils/types'
NavBar,
TimeWindows, const type = ref<string>('')
Chart const window = ref<Window | undefined>(undefined)
},
setup() {
const type = ref(null)
const window = ref({})
const router = useRouter() const router = useRouter()
const currentRoute = router.currentRoute const currentRoute = useRoute()
if (currentRoute.value.params.type) type.value = currentRoute.value.params.type if (currentRoute.params.type) type.value = currentRoute.params.type as string
if (currentRoute.value.params.window) window.value = { label: currentRoute.value.params.window } if (currentRoute.params.window) window.value = windows.find((w) => w.label === currentRoute.params.window)
const updateRoute = () => { const updateRoute = () => {
if (type.value) { if (type.value) {
const route = { const route = {
name: 'view', name: 'view',
params: { params: {
type: type.value, type: type.value,
window: window.value.label ? window.value.label.replace(' ', '-') : undefined window: window.value?.label.replace(' ', '-')
} }
} }
router.push(route) router.push(route)
} }
} }
const setType = (newType) => { const setType = (newType: string) => {
type.value = newType type.value = newType
updateRoute() updateRoute()
} }
const setWindow = (newWindow) => { const setWindow = (newWindow: Window) => {
window.value = newWindow window.value = newWindow
updateRoute() updateRoute()
} }
return {
type,
window,
setType,
setWindow
}
}
}
</script> </script>
<style scoped> <style scoped>
#app { #app {

View File

@@ -21,45 +21,40 @@
<div class="navbar-start"> <div class="navbar-start">
<a <a
class="navbar-item" class="navbar-item"
:class="{ 'is-active': type === activeType }" :class="{ 'is-active': navType === activeType }"
:key="type" :key="navType"
v-for="type in navTypes" v-for="navType in navTypes"
@click="setType(type)" @click="setType(navType)"
>{{ capitalizeFirstLetter(type) }}</a >{{ capitalizeFirstLetter(navType) }}</a
> >
</div> </div>
</div> </div>
</nav> </nav>
</template> </template>
<script> <script setup lang="ts">
import { ref, onMounted } from 'vue'
import { capitalizeFirstLetter } from '@/utils/helpers' import { capitalizeFirstLetter } from '@/utils/helpers'
export default { import { ref, onMounted } from 'vue'
props: ['activeType'],
setup(props, { emit }) { const props = defineProps<{
activeType: string
}>()
const emit = defineEmits<{
(e: 'set-type', type: string): void
}>()
const toggled = ref(false) const toggled = ref(false)
const navTypes = ref(['temperatuur', 'luchtvochtigheid']) const navTypes = ref<string[]>(['temperatuur', 'luchtvochtigheid'])
onMounted(() => { onMounted(() => {
if (!props.activeType) { if (!props.activeType) {
emit('set-type', navTypes.value[0]) emit('set-type', navTypes.value[0])
} }
}) })
const toggleMenu = () => { const toggleMenu = () => (toggled.value = !toggled.value)
toggled.value = !toggled.value const setType = (type: string) => {
}
const setType = (type) => {
toggled.value = false toggled.value = false
emit('set-type', type) emit('set-type', type)
} }
return {
capitalizeFirstLetter,
navTypes,
toggled,
toggleMenu,
setType
}
}
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import '@/style/_variables.scss'; @import '@/style/_variables.scss';

View File

@@ -4,84 +4,31 @@
<li <li
v-for="window in windows" v-for="window in windows"
:key="window.label" :key="window.label"
@click="$emit('set-window', window)" @click="emit('set-window', window)"
:class="{ 'is-active': window.label === activeWindow.label }" :class="{ 'is-active': window.label === activeWindow?.label }"
> >
<a>{{ window.label }}</a> <a>{{ window.label }}</a>
</li> </li>
</ul> </ul>
</div> </div>
</template> </template>
<script> <script setup lang="ts">
import { ref, onMounted } from 'vue' import { onMounted, defineProps, defineEmits } from 'vue'
import dayjs from 'dayjs' import { windows } from '@/utils/helpers'
export default { import type { Window } from '@/utils/types'
props: {
activeWindow: { const props = defineProps<{
type: Object activeWindow: Window | undefined
} }>()
},
setup(props, { emit }) { const emit = defineEmits<{
const windows = ref([ (e: 'set-window', window: Window): void
{ }>()
label: 'afgelopen uur',
getStart: () => dayjs().subtract(1, 'hour').unix(),
getEnd: () => dayjs().unix(),
format: 'HH:mm',
interval: 4
},
{
label: '24 uur',
getStart: () => dayjs().subtract(1, 'days').unix(),
getEnd: () => dayjs().unix(),
format: 'HH:mm',
interval: 4
},
{
label: 'vandaag',
getStart: () => dayjs().startOf('day').add(1, 'day').subtract(24, 'hours').unix(),
getEnd: () => dayjs().unix(),
format: 'HH:mm',
interval: 4
},
{
label: '3 dagen',
getStart: () => dayjs().startOf('day').add(1, 'day').subtract(3, 'days').unix(),
getEnd: () => dayjs().unix(),
format: 'ddd D/M',
interval: 24
},
{
label: 'week',
getStart: () => dayjs().startOf('day').add(1, 'day').subtract(7, 'days').unix(),
getEnd: () => dayjs().unix(),
format: 'ddd D/M',
interval: 24
},
{
label: 'maand',
getStart: () => dayjs().startOf('day').add(1, 'day').subtract(1, 'months').unix(),
getEnd: () => dayjs().unix(),
format: 'ddd D/M',
interval: 24
},
{
label: 'jaar',
getStart: () => dayjs().startOf('day').add(1, 'day').subtract(1, 'year').unix(),
getEnd: () => dayjs().unix(),
format: 'ddd D/M',
interval: 24 * 7
}
])
onMounted(() => { onMounted(() => {
const activeWindow = !props.activeWindow.label const activeWindow = !props.activeWindow?.label
? windows.value[1] ? windows[1]
: windows.value.find((w) => w.label === props.activeWindow.label.replace('-', ' ')) : windows.find((w) => w.label === props.activeWindow?.label.replace('-', ' '))
emit('set-window', activeWindow) if (activeWindow) emit('set-window', activeWindow)
}) })
return {
windows
}
}
}
</script> </script>

View File

@@ -1,3 +0,0 @@
export function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1)
}

58
src/utils/helpers.ts Normal file
View File

@@ -0,0 +1,58 @@
import dayjs from 'dayjs'
import type { Window } from '@/utils/types'
export function capitalizeFirstLetter(string: string): string {
return string.charAt(0).toUpperCase() + string.slice(1)
}
export const windows: Window[] = [
{
label: 'afgelopen uur',
getStart: () => dayjs().subtract(1, 'hour').unix(),
getEnd: () => dayjs().unix(),
format: 'HH:mm',
interval: 4
},
{
label: '24 uur',
getStart: () => dayjs().subtract(1, 'days').unix(),
getEnd: () => dayjs().unix(),
format: 'HH:mm',
interval: 4
},
{
label: 'vandaag',
getStart: () => dayjs().startOf('day').add(1, 'day').subtract(24, 'hours').unix(),
getEnd: () => dayjs().unix(),
format: 'HH:mm',
interval: 4
},
{
label: '3 dagen',
getStart: () => dayjs().startOf('day').add(1, 'day').subtract(3, 'days').unix(),
getEnd: () => dayjs().unix(),
format: 'ddd D/M',
interval: 24
},
{
label: 'week',
getStart: () => dayjs().startOf('day').add(1, 'day').subtract(7, 'days').unix(),
getEnd: () => dayjs().unix(),
format: 'ddd D/M',
interval: 24
},
{
label: 'maand',
getStart: () => dayjs().startOf('day').add(1, 'day').subtract(1, 'months').unix(),
getEnd: () => dayjs().unix(),
format: 'ddd D/M',
interval: 24
},
{
label: 'jaar',
getStart: () => dayjs().startOf('day').add(1, 'day').subtract(1, 'year').unix(),
getEnd: () => dayjs().unix(),
format: 'ddd D/M',
interval: 24 * 7
}
]

7
src/utils/types.ts Normal file
View File

@@ -0,0 +1,7 @@
export interface Window {
label: string
getStart: { (): number }
getEnd: { (): number }
format: string
interval: number
}

8
tsconfig.config.json Normal file
View File

@@ -0,0 +1,8 @@
{
"extends": "@vue/tsconfig/tsconfig.node.json",
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
"compilerOptions": {
"composite": true,
"types": ["node"]
}
}

16
tsconfig.json Normal file
View File

@@ -0,0 +1,16 @@
{
"extends": "@vue/tsconfig/tsconfig.web.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"references": [
{
"path": "./tsconfig.config.json"
}
]
}

View File

@@ -12,6 +12,6 @@ export default defineConfig({
} }
}, },
server: { server: {
port: '8080' port: 8080
} }
}) })