Compare commits
35 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 | ||
|
|
1c59c363ee | ||
|
|
1d99f26fec | ||
|
|
49edb0e627 | ||
|
|
f011e71ae1 | ||
|
|
00c363f808 | ||
|
|
0b2f749ae9 | ||
|
|
cf62a1e6e3 | ||
|
|
8df84d782f | ||
|
|
f0deffafe1 | ||
|
|
a291da661d | ||
|
|
66c3193bc9 | ||
|
|
ac7be49cef | ||
|
|
fa79b77093 | ||
|
|
5823947933 | ||
|
|
333837fb57 | ||
|
|
61fc83996b | ||
|
|
9ddb37e9bb |
@@ -1,5 +1,14 @@
|
||||
# @nhost/dashboard
|
||||
|
||||
## 0.20.27
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fa79b7709: chore(dashboard): tweaks and fixes to the service form and dialog
|
||||
- 8df84d782: fix(dashboard): allow resetting custom domains
|
||||
- @nhost/react-apollo@6.0.0
|
||||
- @nhost/nextjs@1.13.39
|
||||
|
||||
## 0.20.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/dashboard",
|
||||
"version": "0.20.26",
|
||||
"version": "0.20.27",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import type { IconProps } from '@/components/ui/v2/icons';
|
||||
|
||||
function ArrowsClockwise(props: IconProps) {
|
||||
return (
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
aria-label="Update"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M11.0103 6.23227H14.0103V3.23227"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M4.11084 4.11091C4.62156 3.60019 5.22788 3.19506 5.89517 2.91866C6.56246 2.64226 7.27766 2.5 7.99993 2.5C8.7222 2.5 9.4374 2.64226 10.1047 2.91866C10.772 3.19506 11.3783 3.60019 11.889 4.11091L14.0103 6.23223"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M4.98975 9.76773H1.98975V12.7677"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M11.8892 11.8891C11.3785 12.3998 10.7722 12.8049 10.1049 13.0813C9.43762 13.3577 8.72242 13.5 8.00015 13.5C7.27788 13.5 6.56269 13.3577 5.89539 13.0813C5.2281 12.8049 4.62179 12.3998 4.11107 11.8891L1.98975 9.76776"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
ArrowsClockwise.displayName = 'NhostArrowsClockwise';
|
||||
|
||||
export default ArrowsClockwise;
|
||||
@@ -0,0 +1 @@
|
||||
export { default as ArrowsClockwise } from './ArrowsClockwise';
|
||||
@@ -8,6 +8,7 @@ import { VerifyDomain } from '@/features/projects/custom-domains/settings/compon
|
||||
import {
|
||||
useGetAuthenticationSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
type ConfigIngressUpdateInput,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
@@ -18,7 +19,7 @@ import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
auth_fqdn: Yup.string().required(),
|
||||
auth_fqdn: Yup.string(),
|
||||
});
|
||||
|
||||
export type AuthDomainFormValues = Yup.InferType<typeof validationSchema>;
|
||||
@@ -43,13 +44,14 @@ export default function AuthDomain() {
|
||||
},
|
||||
});
|
||||
|
||||
const { networking } = data?.config?.auth?.resources || {};
|
||||
const initialValue = networking?.ingresses?.[0]?.fqdn?.[0];
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && data) {
|
||||
const { networking } = data?.config?.auth?.resources || {};
|
||||
const fqdn = networking?.ingresses?.[0]?.fqdn?.[0];
|
||||
form.reset({ auth_fqdn: fqdn });
|
||||
form.reset({ auth_fqdn: initialValue });
|
||||
}
|
||||
}, [data, loading, form]);
|
||||
}, [data, loading, form, initialValue]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
@@ -71,6 +73,9 @@ export default function AuthDomain() {
|
||||
const auth_fqdn = watch('auth_fqdn');
|
||||
|
||||
async function handleSubmit(formValues: AuthDomainFormValues) {
|
||||
const ingresses: ConfigIngressUpdateInput[] =
|
||||
formValues.auth_fqdn.length > 0 ? [{ fqdn: [formValues.auth_fqdn] }] : [];
|
||||
|
||||
const updateConfigPromise = updateConfig({
|
||||
variables: {
|
||||
appId: currentProject.id,
|
||||
@@ -78,11 +83,7 @@ export default function AuthDomain() {
|
||||
auth: {
|
||||
resources: {
|
||||
networking: {
|
||||
ingresses: [
|
||||
{
|
||||
fqdn: [formValues.auth_fqdn],
|
||||
},
|
||||
],
|
||||
ingresses,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -118,7 +119,8 @@ export default function AuthDomain() {
|
||||
description="Enter below your custom domain for the authentication service."
|
||||
slotProps={{
|
||||
submitButton: {
|
||||
disabled: !isDirty || maintenanceActive || !isVerified,
|
||||
disabled:
|
||||
!isDirty || maintenanceActive || (!isVerified && !initialValue),
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { VerifyDomain } from '@/features/projects/custom-domains/settings/compon
|
||||
import {
|
||||
useGetHasuraSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
type ConfigIngressUpdateInput,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
@@ -18,7 +19,7 @@ import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
hasura_fqdn: Yup.string().required(),
|
||||
hasura_fqdn: Yup.string(),
|
||||
});
|
||||
|
||||
export type HasuraDomainFormValues = Yup.InferType<typeof validationSchema>;
|
||||
@@ -43,13 +44,14 @@ export default function HasuraDomain() {
|
||||
},
|
||||
});
|
||||
|
||||
const { networking } = data?.config?.hasura?.resources || {};
|
||||
const initialValue = networking?.ingresses?.[0]?.fqdn?.[0];
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && data) {
|
||||
const { networking } = data?.config?.hasura?.resources || {};
|
||||
const fqdn = networking?.ingresses?.[0]?.fqdn?.[0];
|
||||
form.reset({ hasura_fqdn: fqdn });
|
||||
form.reset({ hasura_fqdn: initialValue });
|
||||
}
|
||||
}, [data, loading, form]);
|
||||
}, [data, loading, form, initialValue]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
@@ -71,6 +73,11 @@ export default function HasuraDomain() {
|
||||
const hasura_fqdn = watch('hasura_fqdn');
|
||||
|
||||
async function handleSubmit(formValues: HasuraDomainFormValues) {
|
||||
const ingresses: ConfigIngressUpdateInput[] =
|
||||
formValues.hasura_fqdn.length > 0
|
||||
? [{ fqdn: [formValues.hasura_fqdn] }]
|
||||
: [];
|
||||
|
||||
const updateConfigPromise = updateConfig({
|
||||
variables: {
|
||||
appId: currentProject.id,
|
||||
@@ -78,11 +85,7 @@ export default function HasuraDomain() {
|
||||
hasura: {
|
||||
resources: {
|
||||
networking: {
|
||||
ingresses: [
|
||||
{
|
||||
fqdn: [formValues.hasura_fqdn],
|
||||
},
|
||||
],
|
||||
ingresses,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -118,7 +121,8 @@ export default function HasuraDomain() {
|
||||
description="Enter below your custom domain for the Hasura/GraphQL service."
|
||||
slotProps={{
|
||||
submitButton: {
|
||||
disabled: !isDirty || maintenanceActive || !isVerified,
|
||||
disabled:
|
||||
!isDirty || maintenanceActive || (!isVerified && !initialValue),
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
|
||||
@@ -21,7 +21,7 @@ interface RunServicePortProps {
|
||||
}
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
runServicePortFQDN: Yup.string().required(),
|
||||
runServicePortFQDN: Yup.string(),
|
||||
});
|
||||
|
||||
export type RunServicePortFormValues = Yup.InferType<typeof validationSchema>;
|
||||
@@ -38,16 +38,18 @@ export default function RunServicePortDomain({
|
||||
const [updateRunServiceConfig] = useUpdateRunServiceConfigMutation();
|
||||
|
||||
const runServicePort = service.config.ports.find((p) => p.port === port);
|
||||
const initialValue = runServicePort?.ingresses?.[0]?.fqdn?.[0];
|
||||
|
||||
const form = useForm<{ runServicePortFQDN: string }>({
|
||||
reValidateMode: 'onSubmit',
|
||||
defaultValues: {
|
||||
runServicePortFQDN: runServicePort?.ingresses?.[0].fqdn?.[0],
|
||||
runServicePortFQDN: initialValue,
|
||||
},
|
||||
resolver: yupResolver(validationSchema),
|
||||
});
|
||||
|
||||
const { formState, register, watch } = form;
|
||||
const isDirty = Object.keys(formState.dirtyFields).length > 0;
|
||||
|
||||
const runServicePortFQDN = watch('runServicePortFQDN');
|
||||
|
||||
@@ -68,7 +70,10 @@ export default function RunServicePortDomain({
|
||||
if (rest.port === port) {
|
||||
return {
|
||||
...rest,
|
||||
ingresses: [{ fqdn: [formValues.runServicePortFQDN] }],
|
||||
ingresses:
|
||||
formValues.runServicePortFQDN.length > 0
|
||||
? [{ fqdn: [formValues.runServicePortFQDN] }]
|
||||
: [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -128,7 +133,12 @@ export default function RunServicePortDomain({
|
||||
<Button
|
||||
variant="outlined"
|
||||
type="submit"
|
||||
disabled={loading || !isVerified || maintenanceActive}
|
||||
disabled={
|
||||
loading ||
|
||||
!isDirty ||
|
||||
maintenanceActive ||
|
||||
(!isVerified && !initialValue)
|
||||
}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Form } from '@/components/form/Form';
|
||||
import { Alert } from '@/components/ui/v2/Alert';
|
||||
import { Box } from '@/components/ui/v2/Box';
|
||||
import { Button } from '@/components/ui/v2/Button';
|
||||
import { ArrowsClockwise } from '@/components/ui/v2/icons/ArrowsClockwise';
|
||||
import { CopyIcon } from '@/components/ui/v2/icons/CopyIcon';
|
||||
import { InfoIcon } from '@/components/ui/v2/icons/InfoIcon';
|
||||
import { PlusIcon } from '@/components/ui/v2/icons/PlusIcon';
|
||||
@@ -344,7 +345,7 @@ export default function ServiceForm({
|
||||
<Tooltip title="Name of the service, must be unique per project.">
|
||||
<InfoIcon
|
||||
aria-label="Info"
|
||||
className="h-4 w-4"
|
||||
className="w-4 h-4"
|
||||
color="primary"
|
||||
/>
|
||||
</Tooltip>
|
||||
@@ -384,7 +385,7 @@ export default function ServiceForm({
|
||||
>
|
||||
<InfoIcon
|
||||
aria-label="Info"
|
||||
className="h-4 w-4"
|
||||
className="w-4 h-4"
|
||||
color="primary"
|
||||
/>
|
||||
</Tooltip>
|
||||
@@ -415,7 +416,7 @@ export default function ServiceForm({
|
||||
<Tooltip title="Command to run when to start the service. This is optional as the image may already have a baked-in command.">
|
||||
<InfoIcon
|
||||
aria-label="Info"
|
||||
className="h-4 w-4"
|
||||
className="w-4 h-4"
|
||||
color="primary"
|
||||
/>
|
||||
</Tooltip>
|
||||
@@ -459,7 +460,7 @@ export default function ServiceForm({
|
||||
{createServiceFormError && (
|
||||
<Alert
|
||||
severity="error"
|
||||
className="grid grid-flow-col items-center justify-between px-4 py-3"
|
||||
className="grid items-center justify-between grid-flow-col px-4 py-3"
|
||||
>
|
||||
<span className="text-left">
|
||||
<strong>Error:</strong> {createServiceFormError.message}
|
||||
@@ -482,7 +483,7 @@ export default function ServiceForm({
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
startIcon={<PlusIcon />}
|
||||
startIcon={serviceID ? <ArrowsClockwise /> : <PlusIcon />}
|
||||
>
|
||||
{serviceID ? 'Update' : 'Create'}
|
||||
</Button>
|
||||
|
||||
@@ -55,7 +55,8 @@ export default function ServiceDetailsDialog({
|
||||
.filter((port) => port.publish)
|
||||
.map((port) => (
|
||||
<InfoCard
|
||||
title={`${port.type}:${port.port}`}
|
||||
key={String(port.port)}
|
||||
title={`${port.type} <--> ${port.port}`}
|
||||
value={getPortURL(port.port)}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.1'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.21.2'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -28,7 +28,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @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
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@nhost-examples/vue-apollo",
|
||||
"private": true,
|
||||
"version": "0.0.8",
|
||||
"version": "0.0.9",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
@@ -17,14 +17,16 @@
|
||||
"@apollo/client": "^3.7.1",
|
||||
"@mdi/font": "5.9.55",
|
||||
"@nhost/apollo": "*",
|
||||
"@nhost/nhost-js": "*",
|
||||
"@nhost/vue": "*",
|
||||
"@vue/apollo-composable": "4.0.0-alpha.18",
|
||||
"graphql": "15.7.2",
|
||||
"graphql": "^16.8.1",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"roboto-fontface": "*",
|
||||
"vite-plugin-vuetify": "^1.0.1",
|
||||
"vue": "^3.2.41",
|
||||
"vue-router": "^4.1.6",
|
||||
"vue3-dropzone": "^2.1.2",
|
||||
"vuetify": "3.0.0-beta.10",
|
||||
"webfontloader": "^1.0.0"
|
||||
},
|
||||
@@ -35,7 +37,7 @@
|
||||
"@xstate/inspect": "^0.6.2",
|
||||
"sass": "1.32.0",
|
||||
"typescript": "4.9.4",
|
||||
"vite": "^4.0.2",
|
||||
"vite": "^4.5.0",
|
||||
"vue-tsc": "^0.38.9"
|
||||
},
|
||||
"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="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="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 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>
|
||||
</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 SignUp from './pages/sign-up/IndexPage.vue'
|
||||
import Signout from './pages/SignoutPage.vue'
|
||||
import StoragePage from './pages/StoragePage.vue'
|
||||
|
||||
export const routes: RouteRecordRaw[] = [
|
||||
{ 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 } }
|
||||
]
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @nhost/react-apollo
|
||||
|
||||
## 6.0.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [00c363f80]
|
||||
- Updated dependencies [66c3193bc]
|
||||
- @nhost/react@2.1.0
|
||||
|
||||
## 5.0.38
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/react-apollo",
|
||||
"version": "5.0.38",
|
||||
"version": "6.0.0",
|
||||
"description": "Nhost React Apollo client",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @nhost/react-urql
|
||||
|
||||
## 3.0.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [00c363f80]
|
||||
- Updated dependencies [66c3193bc]
|
||||
- @nhost/react@2.1.0
|
||||
|
||||
## 2.0.33
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/react-urql",
|
||||
"version": "2.0.33",
|
||||
"version": "3.0.0",
|
||||
"description": "Nhost React URQL client",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
|
||||
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.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.2'
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @nhost/nextjs
|
||||
|
||||
## 1.13.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [00c363f80]
|
||||
- Updated dependencies [66c3193bc]
|
||||
- @nhost/react@2.1.0
|
||||
|
||||
## 1.13.38
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/nextjs",
|
||||
"version": "1.13.38",
|
||||
"version": "1.13.39",
|
||||
"description": "Nhost NextJS library",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
|
||||
@@ -25,7 +25,7 @@ httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 16
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.20.1'
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @nhost/react
|
||||
|
||||
## 2.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 66c3193bc: Update useChangePassword hook interface to include ActionLoadingState
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 00c363f80: fix(docs): update changeEmail usage reference
|
||||
|
||||
## 2.0.32
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/react",
|
||||
"version": "2.0.32",
|
||||
"version": "2.1.0",
|
||||
"description": "Nhost React library",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
|
||||
@@ -30,9 +30,7 @@ export interface ChangeEmailHookResult extends ChangeEmailState {
|
||||
* const handleFormSubmit = async (e) => {
|
||||
* e.preventDefault();
|
||||
*
|
||||
* await changeEmail({
|
||||
* email: 'new@example.com',
|
||||
* })
|
||||
* await changeEmail('new@example.com')
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
ActionErrorState,
|
||||
ActionLoadingState,
|
||||
ActionSuccessState,
|
||||
ChangePasswordHandlerResult,
|
||||
changePasswordPromise,
|
||||
@@ -13,7 +14,7 @@ interface ChangePasswordHandler {
|
||||
(password: string): Promise<ChangePasswordHandlerResult>
|
||||
}
|
||||
|
||||
export interface ChangePasswordHookResult extends ActionErrorState, ActionSuccessState {
|
||||
export interface ChangePasswordHookResult extends ActionErrorState, ActionLoadingState, ActionSuccessState {
|
||||
/** Requests the password change. Returns a promise with the current context */
|
||||
changePassword: ChangePasswordHandler
|
||||
}
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @nhost/vue
|
||||
|
||||
## 1.14.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 0c49e757c: feat: add new composable `useMultipleFilesUpload`
|
||||
|
||||
## 1.13.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 00c363f80: fix(docs): update changeEmail usage reference
|
||||
|
||||
## 1.13.38
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/vue",
|
||||
"version": "1.13.38",
|
||||
"version": "1.14.0",
|
||||
"description": "Nhost Vue library",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export * from './client'
|
||||
export * from './useAccessToken'
|
||||
export * from './useAuthInterpreter'
|
||||
export * from './useAuthenticated'
|
||||
export * from './useAuthenticationStatus'
|
||||
export * from './useAuthInterpreter'
|
||||
export * from './useChangeEmail'
|
||||
export * from './useChangePassword'
|
||||
export * from './useConfigMfa'
|
||||
@@ -10,6 +10,7 @@ export * from './useDecodedAccessToken'
|
||||
export * from './useFileUpload'
|
||||
export * from './useHasuraClaim'
|
||||
export * from './useHasuraClaims'
|
||||
export * from './useMultipleFilesUpload'
|
||||
export * from './useNhostClient'
|
||||
export * from './useProviderLink'
|
||||
export * from './useResetPassword'
|
||||
|
||||
@@ -29,9 +29,7 @@ export interface ChangeEmailComposableResult extends ToRefs<ChangeEmailState> {
|
||||
* const handleFormSubmit = async (e) => {
|
||||
* e.preventDefault();
|
||||
*
|
||||
* await changeEmail({
|
||||
* email: 'new@example.com',
|
||||
* })
|
||||
* await changeEmail('new@example.com')
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
|
||||
@@ -8,10 +8,11 @@ import {
|
||||
uploadFilePromise
|
||||
} from '@nhost/nhost-js'
|
||||
import { useInterpret, useSelector } from '@xstate/vue'
|
||||
import { ToRefs } from 'vue'
|
||||
import { InterpreterFrom } from 'xstate'
|
||||
import { useNhostClient } from './useNhostClient'
|
||||
|
||||
export interface FileUploadComposableResult extends FileUploadState {
|
||||
export interface FileUploadComposableResult extends ToRefs<FileUploadState> {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* It has the same signature as `useFileUpload`.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* const Item = ({itemRef}) => {
|
||||
* const { name, progress} = useFileUploadItem(itemRef)
|
||||
* return <li>{name} {progress}</li>
|
||||
* }
|
||||
* ```vue
|
||||
* <!-- Parent component or page -->
|
||||
*
|
||||
* const List = () => {
|
||||
* const { list } = useMultipleFilesUpload()
|
||||
* return <ul>
|
||||
* {list.map((itemRef) => <Item key={item.id} itemRef={item} />)}
|
||||
* </ul>
|
||||
* }
|
||||
* <script lang="ts" setup>
|
||||
* const { files } = useMultipleFilesUpload()
|
||||
* <script lang="ts" setup>
|
||||
*
|
||||
* <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({
|
||||
type: 'ADD',
|
||||
file: params.file,
|
||||
bucketId: params.bucketId || bucketId
|
||||
bucketId: params.bucketId || bucketId.value
|
||||
})
|
||||
}
|
||||
|
||||
@@ -88,14 +109,14 @@ export const useFileUploadItem = (
|
||||
ref.send('DESTROY')
|
||||
}
|
||||
|
||||
const isUploading = useSelector(ref, (state) => state.matches('uploading')).value
|
||||
const isUploaded = useSelector(ref, (state) => state.matches('uploaded')).value
|
||||
const isError = useSelector(ref, (state) => state.matches('error')).value
|
||||
const error = useSelector(ref, (state) => state.context.error || null).value
|
||||
const progress = useSelector(ref, (state) => state.context.progress).value
|
||||
const id = useSelector(ref, (state) => state.context.id).value
|
||||
const bucketId = useSelector(ref, (state) => state.context.bucketId).value
|
||||
const name = useSelector(ref, (state) => state.context.file?.name).value
|
||||
const isUploading = useSelector(ref, (state) => state.matches('uploading'))
|
||||
const isUploaded = useSelector(ref, (state) => state.matches('uploaded'))
|
||||
const isError = useSelector(ref, (state) => state.matches('error'))
|
||||
const error = useSelector(ref, (state) => state.context.error || null)
|
||||
const progress = useSelector(ref, (state) => state.context.progress)
|
||||
const id = useSelector(ref, (state) => state.context.id)
|
||||
const bucketId = useSelector(ref, (state) => state.context.bucketId)
|
||||
const name = useSelector(ref, (state) => state.context.file?.name)
|
||||
|
||||
return {
|
||||
add,
|
||||
@@ -117,7 +138,7 @@ export const useFileUploadItem = (
|
||||
* Use the composable `useFileUpload` to upload a file.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* ```ts
|
||||
* const { add,
|
||||
* upload,
|
||||
* 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