Compare commits
18 Commits
@nhost/das
...
@nhost/vue
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea69d4f0f1 | ||
|
|
212d58bee5 | ||
|
|
c3d6b7beec | ||
|
|
5d5d8ef4f3 | ||
|
|
deb61fe97c | ||
|
|
04d36154b0 | ||
|
|
203cfb10b9 | ||
|
|
9690f871fa | ||
|
|
74a6b93971 | ||
|
|
dd4c0d2430 | ||
|
|
83f2ca5cde | ||
|
|
0c49e757c8 | ||
|
|
e90a9d7696 | ||
|
|
00a06466f5 | ||
|
|
8ca9f76cb2 | ||
|
|
78113dd62a | ||
|
|
adb0ee82c6 | ||
|
|
a41bb6cae6 |
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.1'
|
version = '0.20.1'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.21.2'
|
version = '0.21.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
# @nhost-examples/vue-apollo
|
# @nhost-examples/vue-apollo
|
||||||
|
|
||||||
|
## 0.0.9
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 0c49e757c: feat: add new Storage page to demonstrate how to use the composables `useMultipleFilesUpload` together with `useFileUploadItem`
|
||||||
|
- Updated dependencies [0c49e757c]
|
||||||
|
- @nhost/vue@1.14.0
|
||||||
|
|
||||||
## 0.0.8
|
## 0.0.8
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/vue-apollo",
|
"name": "@nhost-examples/vue-apollo",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.8",
|
"version": "0.0.9",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
@@ -17,14 +17,16 @@
|
|||||||
"@apollo/client": "^3.7.1",
|
"@apollo/client": "^3.7.1",
|
||||||
"@mdi/font": "5.9.55",
|
"@mdi/font": "5.9.55",
|
||||||
"@nhost/apollo": "*",
|
"@nhost/apollo": "*",
|
||||||
|
"@nhost/nhost-js": "*",
|
||||||
"@nhost/vue": "*",
|
"@nhost/vue": "*",
|
||||||
"@vue/apollo-composable": "4.0.0-alpha.18",
|
"@vue/apollo-composable": "4.0.0-alpha.18",
|
||||||
"graphql": "15.7.2",
|
"graphql": "^16.8.1",
|
||||||
"graphql-tag": "^2.12.6",
|
"graphql-tag": "^2.12.6",
|
||||||
"roboto-fontface": "*",
|
"roboto-fontface": "*",
|
||||||
"vite-plugin-vuetify": "^1.0.1",
|
"vite-plugin-vuetify": "^1.0.1",
|
||||||
"vue": "^3.2.41",
|
"vue": "^3.2.41",
|
||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6",
|
||||||
|
"vue3-dropzone": "^2.1.2",
|
||||||
"vuetify": "3.0.0-beta.10",
|
"vuetify": "3.0.0-beta.10",
|
||||||
"webfontloader": "^1.0.0"
|
"webfontloader": "^1.0.0"
|
||||||
},
|
},
|
||||||
@@ -35,7 +37,7 @@
|
|||||||
"@xstate/inspect": "^0.6.2",
|
"@xstate/inspect": "^0.6.2",
|
||||||
"sass": "1.32.0",
|
"sass": "1.32.0",
|
||||||
"typescript": "4.9.4",
|
"typescript": "4.9.4",
|
||||||
"vite": "^4.0.2",
|
"vite": "^4.5.0",
|
||||||
"vue-tsc": "^0.38.9"
|
"vue-tsc": "^0.38.9"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
|
|||||||
1657
examples/vue-apollo/pnpm-lock.yaml
generated
Normal file
1657
examples/vue-apollo/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
97
examples/vue-apollo/src/components/FileDropZone.vue
Normal file
97
examples/vue-apollo/src/components/FileDropZone.vue
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, toRaw, unref, type Ref } from 'vue'
|
||||||
|
import { useDropzone, type FileRejectReason } from 'vue3-dropzone'
|
||||||
|
|
||||||
|
const { multiple } = defineProps({
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['onDrop'])
|
||||||
|
|
||||||
|
const files: Ref<File[]> = ref([])
|
||||||
|
const errors: Ref<FileRejectReason[]> = ref([])
|
||||||
|
|
||||||
|
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
||||||
|
onDrop,
|
||||||
|
multiple
|
||||||
|
})
|
||||||
|
|
||||||
|
function onDrop(acceptFiles: File[], rejectReasons: FileRejectReason[]) {
|
||||||
|
files.value = acceptFiles
|
||||||
|
errors.value = rejectReasons
|
||||||
|
|
||||||
|
emit('onDrop', toRaw(unref(files)))
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="dropzone" v-bind="getRootProps()">
|
||||||
|
<div
|
||||||
|
class="border"
|
||||||
|
:class="{
|
||||||
|
isDragActive
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<input v-bind="getInputProps()" />
|
||||||
|
<p v-if="isDragActive">Drop here ...</p>
|
||||||
|
<p v-else>Drag and drop here, or Click to select</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.dropzone,
|
||||||
|
.files {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px, rgba(60, 64, 67, 0.15) 0px 1px 3px 1px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border {
|
||||||
|
border: 2px dashed #ccc;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
&.isDragActive {
|
||||||
|
border: 2px dashed #ffb300;
|
||||||
|
background: rgb(255 167 18 / 20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item {
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
background: rgb(255 167 18 / 20%);
|
||||||
|
padding: 7px;
|
||||||
|
padding-left: 15px;
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-file {
|
||||||
|
background: red;
|
||||||
|
color: #fff;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
34
examples/vue-apollo/src/components/FileUploadItem.vue
Normal file
34
examples/vue-apollo/src/components/FileUploadItem.vue
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { FileItemRef } from '@nhost/nhost-js'
|
||||||
|
import { useFileUploadItem } from '@nhost/vue'
|
||||||
|
|
||||||
|
const { file } = defineProps<{ file: FileItemRef }>()
|
||||||
|
|
||||||
|
const { name, progress } = useFileUploadItem(file)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<span class="file_name">{{ name }}</span>
|
||||||
|
<v-progress-linear v-model="progress" color="green">
|
||||||
|
{{ progress }}
|
||||||
|
</v-progress-linear>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="css" scoped>
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file_name {
|
||||||
|
margin-right: 1rem;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -3,8 +3,14 @@
|
|||||||
<v-list-item title="Home" to="/" value="home" prepend-icon="mdi-home" />
|
<v-list-item title="Home" to="/" value="home" prepend-icon="mdi-home" />
|
||||||
<v-list-item title="Profile" to="/profile" value="profile" prepend-icon="mdi-account" />
|
<v-list-item title="Profile" to="/profile" value="profile" prepend-icon="mdi-account" />
|
||||||
<v-list-item title="Apollo" to="/apollo" value="apollo" prepend-icon="mdi-api" />
|
<v-list-item title="Apollo" to="/apollo" value="apollo" prepend-icon="mdi-api" />
|
||||||
|
<v-list-item title="Storage" to="/storage" value="storage" prepend-icon="mdi-server" />
|
||||||
<v-list-item title="About" to="/about" value="about" prepend-icon="mdi-information" />
|
<v-list-item title="About" to="/about" value="about" prepend-icon="mdi-information" />
|
||||||
<v-list-item v-if="authenticated" title="Sign out" prepend-icon="mdi-exit-to-app" @click="signOutHandler" />
|
<v-list-item
|
||||||
|
v-if="authenticated"
|
||||||
|
title="Sign out"
|
||||||
|
prepend-icon="mdi-exit-to-app"
|
||||||
|
@click="signOutHandler"
|
||||||
|
/>
|
||||||
</v-list>
|
</v-list>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
129
examples/vue-apollo/src/pages/StoragePage.vue
Normal file
129
examples/vue-apollo/src/pages/StoragePage.vue
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
<template>
|
||||||
|
<div className="d-flex align-center flex-column">
|
||||||
|
<h1>Storage</h1>
|
||||||
|
<v-card width="400" class="singleFileUpload" tile>
|
||||||
|
<v-card-title>Upload a single file</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
<FileDropZone @on-drop="onDropSingleFile" />
|
||||||
|
<span v-if="isUploading" class="upload_status">Uploading...</span>
|
||||||
|
<span v-if="isUploaded" class="upload_status upload_success">Upload Succeeded</span>
|
||||||
|
<span v-if="isError" class="upload_status upload_error">Upload Failed</span>
|
||||||
|
<div v-if="fileToUpload" class="file_progress">
|
||||||
|
<span class="file_progress_name">{{ fileToUpload.name }}</span>
|
||||||
|
<v-progress-linear v-model="progress" color="green">
|
||||||
|
{{ progress }}
|
||||||
|
</v-progress-linear>
|
||||||
|
<button class="clearButton" @click="clearFile">Clear</button>
|
||||||
|
</div>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
|
||||||
|
<v-card width="400" tile class="relative">
|
||||||
|
<v-card-title>Upload multiple files</v-card-title>
|
||||||
|
<v-card-text class="footer">
|
||||||
|
<FileDropZone :multiple="true" @on-drop="onDropMultipleFiles" />
|
||||||
|
<span v-if="isUploadingAll" class="upload_status">Uploading...</span>
|
||||||
|
<span v-if="isUploadedAll" class="upload_status upload_success">Upload Succeeded</span>
|
||||||
|
<span v-if="isErrorAll" class="upload_status upload_error">Upload Failed</span>
|
||||||
|
</v-card-text>
|
||||||
|
|
||||||
|
<div v-for="(file, index) of files" :key="index">
|
||||||
|
<FileUploadItem :file="file" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="relative buttonsContainer">
|
||||||
|
<v-btn
|
||||||
|
class="mb-2 text-white w-100"
|
||||||
|
:disabled="!files.length"
|
||||||
|
variant="elevated"
|
||||||
|
color="green"
|
||||||
|
@click="uploadAll"
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</v-btn>
|
||||||
|
<v-btn class="w-100" @click="clear"> Clear </v-btn>
|
||||||
|
</div>
|
||||||
|
</v-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useFileUpload, useMultipleFilesUpload } from '@nhost/vue'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import FileDropZone from '../components/FileDropZone.vue'
|
||||||
|
import FileUploadItem from '../components/FileUploadItem.vue'
|
||||||
|
|
||||||
|
const fileToUpload = ref<File | null>(null)
|
||||||
|
|
||||||
|
const { upload, progress, isUploaded, isUploading, isError } = useFileUpload()
|
||||||
|
|
||||||
|
const onDropSingleFile = async ([file]: File[]) => {
|
||||||
|
fileToUpload.value = file
|
||||||
|
upload({ file })
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearFile = () => {
|
||||||
|
fileToUpload.value = null
|
||||||
|
isUploaded.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
add,
|
||||||
|
upload: uploadAll,
|
||||||
|
isUploaded: isUploadedAll,
|
||||||
|
isUploading: isUploadingAll,
|
||||||
|
isError: isErrorAll,
|
||||||
|
files,
|
||||||
|
clear
|
||||||
|
} = useMultipleFilesUpload()
|
||||||
|
|
||||||
|
const onDropMultipleFiles = (files: File[]) => {
|
||||||
|
add({ files })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="css" scoped>
|
||||||
|
.buttonsContainer {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload_success {
|
||||||
|
color: 'green';
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload_error {
|
||||||
|
color: 'red';
|
||||||
|
}
|
||||||
|
|
||||||
|
.file_progress {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file_progress_name {
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload_status {
|
||||||
|
display: block;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.singleFileUpload {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearButton {
|
||||||
|
margin-left: 1rem;
|
||||||
|
background: red;
|
||||||
|
color: #fff;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.relative {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -13,6 +13,7 @@ import SignUpEmailPasword from './pages/sign-up/EmailPassword.vue'
|
|||||||
import SignUpEmailPaswordless from './pages/sign-up/EmailPasswordless.vue'
|
import SignUpEmailPaswordless from './pages/sign-up/EmailPasswordless.vue'
|
||||||
import SignUp from './pages/sign-up/IndexPage.vue'
|
import SignUp from './pages/sign-up/IndexPage.vue'
|
||||||
import Signout from './pages/SignoutPage.vue'
|
import Signout from './pages/SignoutPage.vue'
|
||||||
|
import StoragePage from './pages/StoragePage.vue'
|
||||||
|
|
||||||
export const routes: RouteRecordRaw[] = [
|
export const routes: RouteRecordRaw[] = [
|
||||||
{ path: '/', component: Index, meta: { auth: true } },
|
{ path: '/', component: Index, meta: { auth: true } },
|
||||||
@@ -50,5 +51,6 @@ export const routes: RouteRecordRaw[] = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ path: '/apollo', component: ApolloPage, meta: { auth: true } }
|
{ path: '/apollo', component: ApolloPage, meta: { auth: true } },
|
||||||
|
{ path: '/storage', component: StoragePage, meta: { auth: true } }
|
||||||
]
|
]
|
||||||
|
|||||||
805
observability/dashboards/ingress_metrics.json
Executable file
805
observability/dashboards/ingress_metrics.json
Executable file
@@ -0,0 +1,805 @@
|
|||||||
|
{
|
||||||
|
"__inputs": [
|
||||||
|
{
|
||||||
|
"name": "DS_PROMETHEUS",
|
||||||
|
"label": "Prometheus",
|
||||||
|
"description": "",
|
||||||
|
"type": "datasource",
|
||||||
|
"pluginId": "prometheus",
|
||||||
|
"pluginName": "Prometheus"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"__elements": {},
|
||||||
|
"__requires": [
|
||||||
|
{
|
||||||
|
"type": "grafana",
|
||||||
|
"id": "grafana",
|
||||||
|
"name": "Grafana",
|
||||||
|
"version": "9.2.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "datasource",
|
||||||
|
"id": "prometheus",
|
||||||
|
"name": "Prometheus",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "panel",
|
||||||
|
"id": "timeseries",
|
||||||
|
"name": "Time series",
|
||||||
|
"version": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"builtIn": 1,
|
||||||
|
"datasource": {
|
||||||
|
"type": "grafana",
|
||||||
|
"uid": "-- Grafana --"
|
||||||
|
},
|
||||||
|
"enable": true,
|
||||||
|
"hide": true,
|
||||||
|
"iconColor": "rgba(0, 211, 255, 1)",
|
||||||
|
"name": "Annotations & Alerts",
|
||||||
|
"target": {
|
||||||
|
"limit": 100,
|
||||||
|
"matchAny": false,
|
||||||
|
"tags": [],
|
||||||
|
"type": "dashboard"
|
||||||
|
},
|
||||||
|
"type": "dashboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": null,
|
||||||
|
"links": [],
|
||||||
|
"liveNow": false,
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"collapsed": false,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 1,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 6,
|
||||||
|
"panels": [],
|
||||||
|
"title": "General",
|
||||||
|
"type": "row"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"description": "Number of requests by method/function",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 0,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "auto",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 1
|
||||||
|
},
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum by(method, route) (increase(nginx_ingress_controller_requests{method=~\"$method\",ingress=~\"$ingress\"}[$__rate_interval]))",
|
||||||
|
"format": "time_series",
|
||||||
|
"interval": "2m",
|
||||||
|
"legendFormat": "{{method}} {{route}}",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Requests",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"description": "Number of requests by status response",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 0,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "auto",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 1
|
||||||
|
},
|
||||||
|
"id": 21,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum by(status) (increase(nginx_ingress_controller_requests{method=~\"$method\",ingress=~\"$ingress\"}[$__rate_interval]))",
|
||||||
|
"format": "time_series",
|
||||||
|
"interval": "2m",
|
||||||
|
"legendFormat": "{{status}}",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Response Status",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"description": "",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 0,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "auto",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "bytes"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 9
|
||||||
|
},
|
||||||
|
"id": 8,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum by(ingress, method) (increase(nginx_ingress_controller_response_size_sum{ingress=~\"$ingress\",method=~\"$method\"}[$__rate_interval])) / sum by(ingress, method) (increase(nginx_ingress_controller_requests{ingress=~\"$ingress\",method=~\"$method\"}[$__rate_interval]))",
|
||||||
|
"interval": "2m",
|
||||||
|
"legendFormat": "{{ method }} - {{ route }}",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Average Response Size",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "continuous-GrYlRd"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"align": "auto",
|
||||||
|
"displayMode": "auto",
|
||||||
|
"filterable": true,
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"matcher": {
|
||||||
|
"id": "byName",
|
||||||
|
"options": "Time"
|
||||||
|
},
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"id": "custom.width",
|
||||||
|
"value": 183
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 9
|
||||||
|
},
|
||||||
|
"id": 4,
|
||||||
|
"options": {
|
||||||
|
"footer": {
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"showHeader": true,
|
||||||
|
"sortBy": [
|
||||||
|
{
|
||||||
|
"desc": true,
|
||||||
|
"displayName": "Value"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"pluginVersion": "9.2.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"exemplar": false,
|
||||||
|
"expr": "ceil(sum by(ingress, method) (increase(nginx_ingress_controller_requests{ingress=~\"$ingress\",method=~\"$method\"}[$__range])))",
|
||||||
|
"format": "table",
|
||||||
|
"instant": true,
|
||||||
|
"interval": "2m",
|
||||||
|
"legendFormat": "{{ingress}} {{method}}",
|
||||||
|
"range": false,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Total Requests",
|
||||||
|
"transformations": [],
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsed": false,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 1,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 17
|
||||||
|
},
|
||||||
|
"id": 26,
|
||||||
|
"panels": [],
|
||||||
|
"title": "Response Times",
|
||||||
|
"type": "row"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"description": "",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 0,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "auto",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 18
|
||||||
|
},
|
||||||
|
"id": 11,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum by(method, ingress) (increase(nginx_ingress_controller_response_duration_seconds_sum{method=~\"$method\", ingress=~\"$ingress\"}[$__rate_interval])) / sum by(method, ingress) (increase(nginx_ingress_controller_response_duration_seconds_count{method=~\"$method\", ingress=~\"$ingress\"}[$__rate_interval]))",
|
||||||
|
"interval": "2m",
|
||||||
|
"legendFormat": "{{ ingress }} - {{ method }}",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Average Response Time",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsed": false,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 1,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 26
|
||||||
|
},
|
||||||
|
"id": 19,
|
||||||
|
"panels": [],
|
||||||
|
"title": "Errors",
|
||||||
|
"type": "row"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"description": "Number of requests that failed divided by the total number of requests",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 0,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "auto",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "percentunit"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 27
|
||||||
|
},
|
||||||
|
"id": 20,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum by(ingress,method) (increase(nginx_ingress_controller_requests{ingress=~\"$ingress\",method=~\"$method\",status=~\"^[4-5].*\"}[$__rate_interval])) / sum by(ingress, method) (increase(nginx_ingress_controller_requests[$__rate_interval]))",
|
||||||
|
"format": "time_series",
|
||||||
|
"interval": "2m",
|
||||||
|
"legendFormat": "{{method}} {{ route }}",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Error Rate",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "continuous-GrYlRd"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"align": "auto",
|
||||||
|
"displayMode": "auto",
|
||||||
|
"filterable": true,
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"matcher": {
|
||||||
|
"id": "byName",
|
||||||
|
"options": "Time"
|
||||||
|
},
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"id": "custom.width",
|
||||||
|
"value": 183
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 27
|
||||||
|
},
|
||||||
|
"id": 10,
|
||||||
|
"options": {
|
||||||
|
"footer": {
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"showHeader": true,
|
||||||
|
"sortBy": [
|
||||||
|
{
|
||||||
|
"desc": true,
|
||||||
|
"displayName": "Value"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"pluginVersion": "9.2.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"exemplar": false,
|
||||||
|
"expr": "ceil(sum by(ingress, method,status) (increase(nginx_ingress_controller_requests{method=~\"$method\",ingress=~\"$ingress\",status=~\"^[4-5].*\"}[$__range])))",
|
||||||
|
"format": "table",
|
||||||
|
"instant": true,
|
||||||
|
"interval": "2m",
|
||||||
|
"legendFormat": "{{ingress}} {{method}}",
|
||||||
|
"range": false,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Total Errors",
|
||||||
|
"transformations": [],
|
||||||
|
"type": "table"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schemaVersion": 37,
|
||||||
|
"style": "dark",
|
||||||
|
"tags": [],
|
||||||
|
"templating": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"current": {},
|
||||||
|
"definition": "label_values(nginx_ingress_controller_requests,ingress)",
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": true,
|
||||||
|
"multi": false,
|
||||||
|
"name": "ingress",
|
||||||
|
"options": [],
|
||||||
|
"query": {
|
||||||
|
"query": "label_values(nginx_ingress_controller_requests,ingress)",
|
||||||
|
"refId": "StandardVariableQuery"
|
||||||
|
},
|
||||||
|
"refresh": 1,
|
||||||
|
"regex": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"sort": 0,
|
||||||
|
"type": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"current": {},
|
||||||
|
"definition": "label_values(nginx_ingress_controller_requests,method)",
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": true,
|
||||||
|
"multi": false,
|
||||||
|
"name": "method",
|
||||||
|
"options": [],
|
||||||
|
"query": {
|
||||||
|
"query": "label_values(nginx_ingress_controller_requests,method)",
|
||||||
|
"refId": "StandardVariableQuery"
|
||||||
|
},
|
||||||
|
"refresh": 1,
|
||||||
|
"regex": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"sort": 0,
|
||||||
|
"type": "query"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-6h",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "",
|
||||||
|
"title": "Ingress Metrics",
|
||||||
|
"uid": "WOWEHb7Sz",
|
||||||
|
"version": 16,
|
||||||
|
"weekStart": ""
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.2'
|
version = '0.20.2'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
|||||||
|
|
||||||
[functions]
|
[functions]
|
||||||
[functions.node]
|
[functions.node]
|
||||||
version = 16
|
version = 18
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.20.1'
|
version = '0.20.1'
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
# @nhost/vue
|
# @nhost/vue
|
||||||
|
|
||||||
|
## 1.14.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- 0c49e757c: feat: add new composable `useMultipleFilesUpload`
|
||||||
|
|
||||||
## 1.13.39
|
## 1.13.39
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/vue",
|
"name": "@nhost/vue",
|
||||||
"version": "1.13.39",
|
"version": "1.14.0",
|
||||||
"description": "Nhost Vue library",
|
"description": "Nhost Vue library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
export * from './client'
|
export * from './client'
|
||||||
export * from './useAccessToken'
|
export * from './useAccessToken'
|
||||||
export * from './useAuthInterpreter'
|
|
||||||
export * from './useAuthenticated'
|
export * from './useAuthenticated'
|
||||||
export * from './useAuthenticationStatus'
|
export * from './useAuthenticationStatus'
|
||||||
|
export * from './useAuthInterpreter'
|
||||||
export * from './useChangeEmail'
|
export * from './useChangeEmail'
|
||||||
export * from './useChangePassword'
|
export * from './useChangePassword'
|
||||||
export * from './useConfigMfa'
|
export * from './useConfigMfa'
|
||||||
@@ -10,6 +10,7 @@ export * from './useDecodedAccessToken'
|
|||||||
export * from './useFileUpload'
|
export * from './useFileUpload'
|
||||||
export * from './useHasuraClaim'
|
export * from './useHasuraClaim'
|
||||||
export * from './useHasuraClaims'
|
export * from './useHasuraClaims'
|
||||||
|
export * from './useMultipleFilesUpload'
|
||||||
export * from './useNhostClient'
|
export * from './useNhostClient'
|
||||||
export * from './useProviderLink'
|
export * from './useProviderLink'
|
||||||
export * from './useResetPassword'
|
export * from './useResetPassword'
|
||||||
|
|||||||
@@ -8,10 +8,11 @@ import {
|
|||||||
uploadFilePromise
|
uploadFilePromise
|
||||||
} from '@nhost/nhost-js'
|
} from '@nhost/nhost-js'
|
||||||
import { useInterpret, useSelector } from '@xstate/vue'
|
import { useInterpret, useSelector } from '@xstate/vue'
|
||||||
|
import { ToRefs } from 'vue'
|
||||||
import { InterpreterFrom } from 'xstate'
|
import { InterpreterFrom } from 'xstate'
|
||||||
import { useNhostClient } from './useNhostClient'
|
import { useNhostClient } from './useNhostClient'
|
||||||
|
|
||||||
export interface FileUploadComposableResult extends FileUploadState {
|
export interface FileUploadComposableResult extends ToRefs<FileUploadState> {
|
||||||
/**
|
/**
|
||||||
* Add the file without uploading it.
|
* Add the file without uploading it.
|
||||||
*/
|
*/
|
||||||
@@ -38,21 +39,41 @@ export type { FileItemRef }
|
|||||||
/**
|
/**
|
||||||
* Use the composable `useFileUploadItem` to control the file upload of a file in a multiple file upload.
|
* Use the composable `useFileUploadItem` to control the file upload of a file in a multiple file upload.
|
||||||
*
|
*
|
||||||
* It has the same signature as `useFileUpload`.
|
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```tsx
|
* ```vue
|
||||||
* const Item = ({itemRef}) => {
|
* <!-- Parent component or page -->
|
||||||
* const { name, progress} = useFileUploadItem(itemRef)
|
|
||||||
* return <li>{name} {progress}</li>
|
|
||||||
* }
|
|
||||||
*
|
*
|
||||||
* const List = () => {
|
* <script lang="ts" setup>
|
||||||
* const { list } = useMultipleFilesUpload()
|
* const { files } = useMultipleFilesUpload()
|
||||||
* return <ul>
|
* <script lang="ts" setup>
|
||||||
* {list.map((itemRef) => <Item key={item.id} itemRef={item} />)}
|
*
|
||||||
* </ul>
|
* <template>
|
||||||
* }
|
* <div v-for="(file, index) of files" :key="index">
|
||||||
|
* <FileUploadItem :file="file" />
|
||||||
|
* </div>
|
||||||
|
* </template>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <!-- FileUploadItem component -->
|
||||||
|
*
|
||||||
|
* <script lang="ts" setup>
|
||||||
|
* import { FileItemRef } from '@nhost/nhost-js'
|
||||||
|
* import { useFileUploadItem } from '@nhost/vue'
|
||||||
|
*
|
||||||
|
* const { file } = defineProps<{ file: FileItemRef }>()
|
||||||
|
*
|
||||||
|
* const { name, progress } = useFileUploadItem(file)
|
||||||
|
* </script>
|
||||||
|
*
|
||||||
|
* <template>
|
||||||
|
* <div>
|
||||||
|
* <span>{{ name }}</span>
|
||||||
|
* <v-progress-linear v-model="progress">
|
||||||
|
* {{ progress }}
|
||||||
|
* </v-progress-linear>
|
||||||
|
* </div>
|
||||||
|
* </template>
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@@ -65,7 +86,7 @@ export const useFileUploadItem = (
|
|||||||
ref.send({
|
ref.send({
|
||||||
type: 'ADD',
|
type: 'ADD',
|
||||||
file: params.file,
|
file: params.file,
|
||||||
bucketId: params.bucketId || bucketId
|
bucketId: params.bucketId || bucketId.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,14 +109,14 @@ export const useFileUploadItem = (
|
|||||||
ref.send('DESTROY')
|
ref.send('DESTROY')
|
||||||
}
|
}
|
||||||
|
|
||||||
const isUploading = useSelector(ref, (state) => state.matches('uploading')).value
|
const isUploading = useSelector(ref, (state) => state.matches('uploading'))
|
||||||
const isUploaded = useSelector(ref, (state) => state.matches('uploaded')).value
|
const isUploaded = useSelector(ref, (state) => state.matches('uploaded'))
|
||||||
const isError = useSelector(ref, (state) => state.matches('error')).value
|
const isError = useSelector(ref, (state) => state.matches('error'))
|
||||||
const error = useSelector(ref, (state) => state.context.error || null).value
|
const error = useSelector(ref, (state) => state.context.error || null)
|
||||||
const progress = useSelector(ref, (state) => state.context.progress).value
|
const progress = useSelector(ref, (state) => state.context.progress)
|
||||||
const id = useSelector(ref, (state) => state.context.id).value
|
const id = useSelector(ref, (state) => state.context.id)
|
||||||
const bucketId = useSelector(ref, (state) => state.context.bucketId).value
|
const bucketId = useSelector(ref, (state) => state.context.bucketId)
|
||||||
const name = useSelector(ref, (state) => state.context.file?.name).value
|
const name = useSelector(ref, (state) => state.context.file?.name)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
add,
|
add,
|
||||||
@@ -117,7 +138,7 @@ export const useFileUploadItem = (
|
|||||||
* Use the composable `useFileUpload` to upload a file.
|
* Use the composable `useFileUpload` to upload a file.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```tsx
|
* ```ts
|
||||||
* const { add,
|
* const { add,
|
||||||
* upload,
|
* upload,
|
||||||
* cancel,
|
* cancel,
|
||||||
|
|||||||
117
packages/vue/src/useMultipleFilesUpload.ts
Normal file
117
packages/vue/src/useMultipleFilesUpload.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import {
|
||||||
|
createMultipleFilesUploadMachine,
|
||||||
|
FileItemRef,
|
||||||
|
MultipleFilesHandlerResult,
|
||||||
|
MultipleFilesUploadState,
|
||||||
|
UploadMultipleFilesActionParams,
|
||||||
|
uploadMultipleFilesPromise
|
||||||
|
} from '@nhost/nhost-js'
|
||||||
|
import { useInterpret, useSelector } from '@xstate/vue'
|
||||||
|
import { Ref, ref, ToRefs } from 'vue'
|
||||||
|
import { useNhostClient } from './useNhostClient'
|
||||||
|
|
||||||
|
export interface MultipleFilesUploadComposableResult extends ToRefs<MultipleFilesUploadState> {
|
||||||
|
/**
|
||||||
|
* Add one or multiple files to add to the list of files to upload.
|
||||||
|
*/
|
||||||
|
add: (
|
||||||
|
params: Required<Pick<UploadMultipleFilesActionParams, 'files'>> &
|
||||||
|
UploadMultipleFilesActionParams
|
||||||
|
) => void
|
||||||
|
/**
|
||||||
|
* Upload the files that has been previously added to the list.
|
||||||
|
*/
|
||||||
|
upload: (params?: UploadMultipleFilesActionParams) => Promise<MultipleFilesHandlerResult>
|
||||||
|
/**
|
||||||
|
* Cancel the ongoing upload. The files that have been successfully uploaded will not be deleted from the server.
|
||||||
|
*/
|
||||||
|
cancel: () => void
|
||||||
|
/**
|
||||||
|
* Clear the list of files.
|
||||||
|
*/
|
||||||
|
clear: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the composable `useMultipleFilesUpload` to upload multiple files.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const {
|
||||||
|
* add,
|
||||||
|
* upload
|
||||||
|
* } = useMultipleFilesUpload()
|
||||||
|
*
|
||||||
|
* const addFiles = async (files) => {
|
||||||
|
* add({files})
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const handleSubmit = async (e) => {
|
||||||
|
* e.preventDefault()
|
||||||
|
* await upload()
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @docs https://docs.nhost.io/reference/vue/use-multiple-files-upload
|
||||||
|
*/
|
||||||
|
export const useMultipleFilesUpload = (): MultipleFilesUploadComposableResult => {
|
||||||
|
const { nhost } = useNhostClient()
|
||||||
|
const errors: Ref<FileItemRef[]> = ref([])
|
||||||
|
|
||||||
|
const service = useInterpret(createMultipleFilesUploadMachine, {}, (state) => {
|
||||||
|
if (state.event.type === 'UPLOAD_ERROR') {
|
||||||
|
errors.value = state.context.files.filter((ref) => ref.getSnapshot()?.context.error)
|
||||||
|
} else if (
|
||||||
|
(state.matches('uploaded') || state.event.type === 'CLEAR') &&
|
||||||
|
errors.value.length > 0
|
||||||
|
) {
|
||||||
|
errors.value = []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const add = (
|
||||||
|
params: Required<Pick<UploadMultipleFilesActionParams, 'files'>> &
|
||||||
|
UploadMultipleFilesActionParams
|
||||||
|
) => {
|
||||||
|
service.send({ type: 'ADD', ...params })
|
||||||
|
}
|
||||||
|
|
||||||
|
const upload = (params?: UploadMultipleFilesActionParams) =>
|
||||||
|
uploadMultipleFilesPromise(
|
||||||
|
{
|
||||||
|
url: nhost.storage.url,
|
||||||
|
accessToken: nhost.auth.getAccessToken(),
|
||||||
|
adminSecret: nhost.adminSecret,
|
||||||
|
...params
|
||||||
|
},
|
||||||
|
service
|
||||||
|
)
|
||||||
|
|
||||||
|
const cancel = () => {
|
||||||
|
service.send('CANCEL')
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
service.send('CLEAR')
|
||||||
|
}
|
||||||
|
|
||||||
|
const isUploading = useSelector(service, (state) => state.matches('uploading'))
|
||||||
|
const isUploaded = useSelector(service, (state) => state.matches('uploaded'))
|
||||||
|
const isError = useSelector(service, (state) => state.matches('error'))
|
||||||
|
|
||||||
|
const progress = useSelector(service, (state) => state.context.progress)
|
||||||
|
const files = useSelector(service, (state) => state.context.files)
|
||||||
|
|
||||||
|
return {
|
||||||
|
upload,
|
||||||
|
add,
|
||||||
|
clear,
|
||||||
|
cancel,
|
||||||
|
progress,
|
||||||
|
isUploaded,
|
||||||
|
isUploading,
|
||||||
|
files,
|
||||||
|
isError,
|
||||||
|
errors
|
||||||
|
}
|
||||||
|
}
|
||||||
613
pnpm-lock.yaml
generated
613
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user