Files
speckle-server/packages/frontend-2/components/developer-settings/CreateTokenDialog.vue
T
andrewwallacespeckle 76cbcef4e6 Feature - FE2 - Developer Settings (#1822)
* WIP Developer Settings

* Access Tokens

* scopes load fix

* mapping to correct struct

* Updates to Application

* Update to apps.js to fix scopes error

* Application table done

* Token confirmation done.

* Application Success

* Fix ts

* Darkmode fixes

* Responsive fix

* Fixes for PR

* Pass size prop to Editable Avatar

* Updates from PR comments

* Section Header - TS Types

* Add Typeguard to Delete Dialog

* Add Description to scopes query

* minor type guard fix

* edit application cache update fix

* Fix Dialog Expansion

* Rename mutations to correct casing

* Remove unneeded import for defineProps

---------

Co-authored-by: Kristaps Fabians Geikins <fabis94@live.com>
2023-10-26 12:51:05 +01:00

129 lines
3.5 KiB
Vue

<template>
<LayoutDialog
v-model:open="isOpen"
max-width="sm"
title="Create Token"
:buttons="dialogButtons"
prevent-close-on-click-outside
>
<form @submit="onSubmit">
<div class="flex flex-col gap-6">
<FormTextInput
v-model="name"
label="Name"
help="A name to remember this token by. For example, the name of the script or application you're planning to use it in!"
name="hookName"
:rules="[isRequired]"
show-required
show-label
type="text"
/>
<FormSelectBadges
v-model="scopes"
multiple
name="scopes"
label="Scopes"
placeholder="Choose Scopes"
help="It's good practice to limit the scopes of your token to the absolute minimum. For example, if your application or script will only read and write streams, select just those scopes."
show-required
:rules="[isItemSelected]"
show-label
:items="apiTokenScopes"
by="id"
/>
</div>
</form>
</LayoutDialog>
</template>
<script setup lang="ts">
import { useMutation } from '@vue/apollo-composable'
import { AllScopes } from '@speckle/shared'
import { LayoutDialog, FormSelectBadges } from '@speckle/ui-components'
import { TokenFormValues } from '~~/lib/developer-settings/helpers/types'
import { createAccessTokenMutation } from '~~/lib/developer-settings/graphql/mutations'
import { isItemSelected, isRequired } from '~~/lib/common/helpers/validation'
import { useForm } from 'vee-validate'
import {
convertThrowIntoFetchResult,
getFirstErrorMessage
} from '~~/lib/common/helpers/graphql'
import { useGlobalToast, ToastNotificationType } from '~~/lib/common/composables/toast'
const emit = defineEmits<{
(e: 'token-created', tokenId: string): void
}>()
const { mutate: createToken } = useMutation(createAccessTokenMutation)
const { triggerNotification } = useGlobalToast()
const { handleSubmit } = useForm<TokenFormValues>()
const isOpen = defineModel<boolean>('open', { required: true })
const name = ref('')
const scopes = ref<typeof apiTokenScopes.value>([])
const apiTokenScopes = computed(() => {
return Object.values(AllScopes).map((value) => ({
id: value,
text: value
}))
})
const onSubmit = handleSubmit(async (tokenFormValues) => {
const result = await createToken({
token: {
name: name.value,
scopes: tokenFormValues.scopes.map((t) => t.id)
}
}).catch(convertThrowIntoFetchResult)
if (result?.data?.apiTokenCreate) {
isOpen.value = false
resetFormFields()
emit('token-created', result.data.apiTokenCreate)
triggerNotification({
type: ToastNotificationType.Success,
title: 'Webhook created',
description: 'The webhook has been successfully created'
})
} else {
const errorMessage = getFirstErrorMessage(result?.errors)
triggerNotification({
type: ToastNotificationType.Danger,
title: 'Failed to create token',
description: errorMessage
})
}
})
const dialogButtons = computed(() => [
{
text: 'Cancel',
props: { color: 'secondary', fullWidth: true, outline: true },
onClick: () => {
isOpen.value = false
}
},
{
text: 'Create',
props: { color: 'primary', fullWidth: true },
onClick: onSubmit
}
])
const resetFormFields = () => {
name.value = ''
scopes.value = []
}
watch(
() => isOpen.value,
(newVal) => {
if (newVal) {
resetFormFields()
}
}
)
</script>