feat(frontend,API): Add PUT operations, integrate API, add first from engine

This commit is contained in:
2025-02-24 08:29:44 +01:00
parent 7c6b6e428c
commit 12ba5da7be
15 changed files with 312 additions and 231 deletions

View File

@@ -8,7 +8,7 @@ info:
email: denis.lugowski@gmail.com
servers:
- url: /api/v3
- url: /
paths:
/application-forms:
@@ -54,18 +54,18 @@ paths:
$ref: "https://api.swaggerhub.com/domains/smartbear-public/ProblemDetails/1.0.0#/components/responses/ServiceUnavailable"
/application-forms/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
get:
summary: Get a specific ApplicationForm
operationId: getApplicationFormById
tags:
- application-form
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
"200":
description: Get application form by ID
@@ -81,18 +81,37 @@ paths:
$ref: "https://api.swaggerhub.com/domains/smartbear-public/ProblemDetails/1.0.0#/components/responses/ServerError"
"503":
$ref: "https://api.swaggerhub.com/domains/smartbear-public/ProblemDetails/1.0.0#/components/responses/ServiceUnavailable"
put:
summary: Updates a ApplicationForm
operationId: updateApplicationForm
tags:
- application-form
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ApplicationFormDto"
responses:
"200":
description: Successfully updated application form
content:
application/json:
schema:
$ref: "#/components/schemas/ApplicationFormDto"
"400":
$ref: "https://api.swaggerhub.com/domains/smartbear-public/ProblemDetails/1.0.0#/components/responses/BadRequest"
"401":
$ref: "https://api.swaggerhub.com/domains/smartbear-public/ProblemDetails/1.0.0#/components/responses/Unauthorized"
"500":
$ref: "https://api.swaggerhub.com/domains/smartbear-public/ProblemDetails/1.0.0#/components/responses/ServerError"
"503":
$ref: "https://api.swaggerhub.com/domains/smartbear-public/ProblemDetails/1.0.0#/components/responses/ServiceUnavailable"
delete:
summary: Delete a ApplicationForm
operationId: deleteApplicationForm
tags:
- application-form
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
"204":
description: Application Form successfully deleted
@@ -148,18 +167,18 @@ paths:
$ref: "https://api.swaggerhub.com/domains/smartbear-public/ProblemDetails/1.0.0#/components/responses/ServiceUnavailable"
/users/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
get:
summary: Get a specific user
operationId: getUserById
tags:
- user
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
"200":
description: Get user by ID
@@ -180,13 +199,6 @@ paths:
operationId: deleteUser
tags:
- user
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
"204":
description: User successfully deleted
@@ -248,18 +260,18 @@ paths:
$ref: "https://api.swaggerhub.com/domains/smartbear-public/ProblemDetails/1.0.0#/components/responses/ServiceUnavailable"
/comments/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
get:
summary: Get a specific comment
operationId: getCommentById
tags:
- comment
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
"200":
description: Get comment by ID
@@ -280,13 +292,6 @@ paths:
operationId: deleteComment
tags:
- comment
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
"204":
description: Comment successfully deleted
@@ -350,18 +355,18 @@ paths:
$ref: "https://api.swaggerhub.com/domains/smartbear-public/ProblemDetails/1.0.0#/components/responses/ServiceUnavailable"
/roles/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
get:
summary: Get a specific role
operationId: getRoleById
tags:
- role
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
"200":
description: Get role by ID
@@ -382,13 +387,6 @@ paths:
operationId: deleteRole
tags:
- role
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
"204":
description: Role successfully deleted
@@ -436,18 +434,18 @@ paths:
$ref: "https://api.swaggerhub.com/domains/smartbear-public/ProblemDetails/1.0.0#/components/responses/ServiceUnavailable"
/files/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
get:
summary: Get a specific file
operationId: getFileById
tags:
- file
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
"200":
description: Get file by ID
@@ -468,13 +466,6 @@ paths:
operationId: deleteFile
tags:
- file
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
"204":
description: File successfully deleted

View File

@@ -1,3 +0,0 @@
import { ApplicationFormApi } from '../.api-client'
export const applicationFormApiClient = new ApplicationFormApi()

View File

@@ -0,0 +1,28 @@
<template>
<div v-for="formElement in formElements" :key="formElement.id">
<component :is="getResolvedComponent(formElement)" />
</div>
</template>
<script setup lang="ts">
import type { FormElementDto } from '~/.api-client'
import { resolveComponent } from 'vue'
defineProps<{
formElements: FormElementDto[]
}>()
// TODO: Lazy loading?
function getResolvedComponent(formElement: FormElementDto) {
switch (formElement.type) {
case 'CHECKBOX':
case 'DROPDOWN':
case 'RADIOBUTTON':
case 'SWITCH':
case 'TEXTFIELD':
return resolveComponent('TheInput')
default:
return resolveComponent('Unimplemented')
}
}
</script>

View File

@@ -0,0 +1,14 @@
<template>
<UFormField :label="label" :name="name">
<UInput v-model="model" />
</UFormField>
</template>
<script setup lang="ts">
defineProps<{
label?: string
name?: string
}>()
const model = defineModel({ type: String })
</script>

View File

@@ -0,0 +1,3 @@
<template>
<div>Element unimplemented:</div>
</template>

View File

@@ -0,0 +1,67 @@
import type { CreateApplicationFormDto, ApplicationFormDto, PagedApplicationFormDto } from '~/.api-client'
const currentApplicationForm: Ref<ApplicationFormDto | undefined> = ref()
export function useApplicationForm() {
const applicationFormApi = useApplicationFormApi()
async function createApplicationForm(
createApplicationFormDto: CreateApplicationFormDto
): Promise<ApplicationFormDto> {
try {
currentApplicationForm.value = await applicationFormApi.createApplicationForm(createApplicationFormDto)
return currentApplicationForm.value
} catch (e) {
console.error('Failed creating application form', e)
return Promise.reject(e)
}
}
async function getAllApplicationForms(): Promise<PagedApplicationFormDto> {
try {
return await applicationFormApi.getAllApplicationForms()
} catch (e) {
console.error('Failed retrieving application forms', e)
return Promise.reject(e)
}
}
async function getApplicationFormById(id: string): Promise<ApplicationFormDto> {
try {
return await applicationFormApi.getApplicationFormById(id)
} catch (e) {
console.error(`Failed retrieving application form with ID ${id}`, e)
return Promise.reject(e)
}
}
async function updateApplicationForm(
id: string,
applicationFormDto: ApplicationFormDto
): Promise<ApplicationFormDto> {
try {
currentApplicationForm.value = await applicationFormApi.updateApplicationForm(id, applicationFormDto)
return currentApplicationForm.value
} catch (e) {
console.error(`Failed deleting application form with ID ${id}`, e)
return Promise.reject(e)
}
}
async function deleteApplicationFormById(id: string): Promise<void> {
try {
return await applicationFormApi.deleteApplicationFormById(id)
} catch (e) {
console.error(`Failed deleting application form with ID ${id}`, e)
return Promise.reject(e)
}
}
return {
createApplicationForm,
getAllApplicationForms,
getApplicationFormById,
updateApplicationForm,
deleteApplicationFormById
}
}

View File

@@ -0,0 +1,47 @@
import { ApplicationFormApi, Configuration } from '../.api-client'
import type { CreateApplicationFormDto, ApplicationFormDto, PagedApplicationFormDto } from '~/.api-client'
import { cleanDoubleSlashes } from 'ufo'
export function useApplicationFormApi() {
const appBaseUrl = useRuntimeConfig().app.baseURL
const { serverApiBaseUrl, serverApiBasePath, clientProxyBasePath } = useRuntimeConfig().public
const basePath = cleanDoubleSlashes(
import.meta.client ? appBaseUrl + clientProxyBasePath : serverApiBaseUrl + serverApiBasePath
)
const applicationFormApiClient = new ApplicationFormApi(new Configuration({ basePath }))
async function createApplicationForm(
createApplicationFormDto: CreateApplicationFormDto
): Promise<ApplicationFormDto> {
return applicationFormApiClient.createApplicationForm({ createApplicationFormDto })
}
async function getAllApplicationForms(): Promise<PagedApplicationFormDto> {
return applicationFormApiClient.getAllApplicationForms()
}
async function getApplicationFormById(id: string): Promise<ApplicationFormDto> {
return applicationFormApiClient.getApplicationFormById({ id })
}
async function updateApplicationForm(
id: string,
applicationFormDto: ApplicationFormDto
): Promise<ApplicationFormDto> {
return applicationFormApiClient.updateApplicationForm({ id, applicationFormDto })
}
async function deleteApplicationFormById(id: string): Promise<void> {
return applicationFormApiClient.deleteApplicationForm({ id })
}
return {
createApplicationForm,
getAllApplicationForms,
getApplicationFormById,
updateApplicationForm,
deleteApplicationFormById
}
}

10
legalconsenthub/index.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
declare module 'nuxt/schema' {
interface PublicRuntimeConfig {
clientProxyBasePath: string
serverApiBaseUrl: string
serverApiBasePath: string
}
}
// It is always important to ensure you import/export something when augmenting a type
export {}

View File

@@ -1,6 +1,6 @@
<template>
<UDashboardGroup>
<UDashboardSearch :groups="groups" />
<UDashboardSearch />
<UDashboardSidebar
collapsible
@@ -8,10 +8,6 @@
class="bg-(--ui-bg-elevated)/25"
:ui="{ footer: 'lg:border-t lg:border-(--ui-border)' }"
>
<template #header="{ collapsed }">
<TeamsMenu :collapsed="collapsed" />
</template>
<template #default="{ collapsed }">
<UDashboardSearchButton :collapsed="collapsed" class="bg-transparent ring-(--ui-border)" />
@@ -19,129 +15,15 @@
<UNavigationMenu :collapsed="collapsed" :items="links[1]" orientation="vertical" class="mt-auto" />
</template>
<template #footer="{ collapsed }">
<UserMenu :collapsed="collapsed" />
</template>
</UDashboardSidebar>
<slot />
<!-- <HelpSlideover /> -->
<NotificationsSlideover />
<!-- <NotificationsSlideover /> -->
</UDashboardGroup>
</template>
<script setup lang="ts">
const route = useRoute()
const toast = useToast()
const links = [
[
{
label: 'Home',
icon: 'i-lucide-house',
to: '/'
},
{
label: 'Inbox',
icon: 'i-lucide-inbox',
to: '/inbox',
badge: '4'
},
{
label: 'Customers',
icon: 'i-lucide-users',
to: '/customers'
},
{
label: 'Settings',
to: '/settings',
icon: 'i-lucide-settings',
defaultOpen: true,
children: [
{
label: 'General',
to: '/settings',
exact: true
},
{
label: 'Members',
to: '/settings/members'
},
{
label: 'Notifications',
to: '/settings/notifications'
},
{
label: 'Security',
to: '/settings/security'
}
]
}
],
[
{
label: 'Feedback',
icon: 'i-lucide-message-circle',
to: 'https://github.com/nuxt-ui-pro/dashboard',
target: '_blank'
},
{
label: 'Help & Support',
icon: 'i-lucide-info',
to: 'https://github.com/nuxt/ui-pro',
target: '_blank'
}
]
]
const groups = computed(() => [
{
id: 'links',
label: 'Go to',
items: links.flat()
},
{
id: 'code',
label: 'Code',
items: [
{
id: 'source',
label: 'View page source',
icon: 'i-simple-icons-github',
to: `https://github.com/nuxt-ui-pro/dashboard/blob/v3/app/pages${route.path === '/' ? '/index' : route.path}.vue`,
target: '_blank'
}
]
}
])
onMounted(async () => {
const cookie = useCookie('cookie-consent')
if (cookie.value === 'accepted') {
return
}
toast.add({
title: 'We use first-party cookies to enhance your experience on our website.',
duration: 0,
close: false,
actions: [
{
label: 'Accept',
color: 'neutral',
variant: 'outline',
onClick: () => {
cookie.value = 'accepted'
}
},
{
label: 'Opt out',
color: 'neutral',
variant: 'ghost'
}
]
})
})
const links = [[], []]
</script>

View File

@@ -1,6 +1,19 @@
export default defineNuxtConfig({
modules: ['@nuxt/ui-pro', '@nuxt/eslint'],
css: ['~/assets/css/main.css'],
runtimeConfig: {
public: {
clientProxyBasePath: 'NOT_SET',
serverApiBaseUrl: 'NOT_SET',
serverApiBasePath: 'NOT_SET'
}
},
components: [
{
path: '~/components',
pathPrefix: false
}
],
typescript: {
typeCheck: true
},

View File

@@ -0,0 +1,46 @@
<template>
<UDashboardPanel id="home">
<template #header>
<UDashboardNavbar title="Home" :ui="{ right: 'gap-3' }">
<template #leading>
<UDashboardSidebarCollapse />
</template>
<template #right>
<UTooltip text="Notifications" :shortcuts="['N']">
<UButton color="neutral" variant="ghost" square>
<UChip color="error" inset>
<UIcon name="i-lucide-bell" class="size-5 shrink-0" />
</UChip>
</UButton>
</UTooltip>
</template>
</UDashboardNavbar>
<UDashboardToolbar>
<template #left />
</UDashboardToolbar>
</template>
<template #body>
<UForm class="space-y-4" :state="{}" @submit="onSubmit">
<FormEngine :form-elements="data?.content[0].formElements ?? []" />
<UButton type="submit">Submit</UButton>
</UForm>
</template>
</UDashboardPanel>
</template>
<script setup lang="ts">
import type { PagedApplicationFormDto } from '~/.api-client'
const { getAllApplicationForms } = useApplicationForm()
const { data } = await useAsyncData<PagedApplicationFormDto>(async () => {
return await getAllApplicationForms()
})
function onSubmit() {
console.log('Submitted')
}
</script>

View File

@@ -15,19 +15,12 @@
</UButton>
</UTooltip>
<UDropdownMenu :items="items">
<UButton icon="i-lucide-plus" size="md" class="rounded-full" />
</UDropdownMenu>
<UButton icon="i-lucide-plus" size="md" class="rounded-full" @click="navigateTo('/create')" />
</template>
</UDashboardNavbar>
<UDashboardToolbar>
<template #left>
<!-- NOTE: The `-ms-1` class is used to align with the `DashboardSidebarCollapse` button here. -->
<HomeDateRangePicker v-model="range" class="-ms-1" />
<HomePeriodSelect v-model="period" :range="range" />
</template>
<template #left> toolbar left </template>
</UDashboardToolbar>
</template>
@@ -39,35 +32,10 @@
</div>
<Register />
<Login />
<HomeStats :period="period" :range="range" />
<HomeChart :period="period" :range="range" />
<HomeSales :period="period" :range="range" />
</template>
</UDashboardPanel>
</template>
<script setup lang="ts">
const session = authClient.useSession()
const items = [
[
{
label: 'New mail',
icon: 'i-lucide-send',
to: '/inbox'
},
{
label: 'New customer',
icon: 'i-lucide-user-plus',
to: '/customers'
}
]
]
const range = shallowRef({
start: new Date(),
end: new Date()
})
const period = ref<string>('daily')
</script>

View File

@@ -0,0 +1,14 @@
import type { H3Event } from 'h3'
import { joinURL } from 'ufo'
export default defineEventHandler((event: H3Event) => {
const { serverApiBaseUrl, clientProxyBasePath } = useRuntimeConfig().public
const escapedClientProxyBasePath = clientProxyBasePath.replace(/^\//, '\\/')
// Use the escaped value in the regex
const path = event.path.replace(new RegExp(`^${escapedClientProxyBasePath}`), '')
const target = joinURL(serverApiBaseUrl, path)
console.log('🔀 proxying request to', target)
return proxyRequest(event, target)
})

View File

@@ -1,5 +1,5 @@
import { auth } from '../../utils/auth'
import { H3Event } from 'h3'
import type { H3Event } from 'h3'
export default defineEventHandler((event: H3Event) => {
return auth.handler(toWebRequest(event))

View File

@@ -5,6 +5,7 @@
// Prevents the following error with openapi generated code (came with nuxt 3.12):
// ERROR(vue-tsc) This parameter property must have an 'override' modifier because it overrides a member in base class 'Error'.
// FILE /Users/denislugowski/Projekte/legalconsenthub/legalconsenthub/.api-client/runtime.ts:276:5
"noImplicitOverride": false
"noImplicitOverride": false,
"noErrorTruncation": true
}
}