refactor: remove pocketbase (#1138)

This commit is contained in:
Jonas Plum
2025-09-02 21:58:08 +02:00
committed by GitHub
parent f28c238135
commit eba2615ec0
435 changed files with 42677 additions and 4730 deletions

View File

@@ -3,7 +3,7 @@ require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
@@ -11,5 +11,8 @@ module.exports = {
],
parserOptions: {
ecmaVersion: 'latest'
},
rules: {
'vue/multi-word-component-names': 'off'
}
}

1781
ui/bun.lock Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

0
ui/dist/.keep vendored Normal file
View File

View File

@@ -9,62 +9,69 @@
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --build --force",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path ../.gitignore",
"format": "prettier --write src/"
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-pattern \"src/components/ui/**\" --ignore-path ../.gitignore",
"format": "prettier --log-level warn --write src/",
"generate": "openapi-generator-cli version-manager set 7.14.0 && JAVA_OPTS=\"-Dlog.level=warn\" openapi-generator-cli generate -i ../openapi.yml -g typescript-fetch -o src/client",
"install:e2e": "playwright install --with-deps",
"test:e2e": "playwright test --timeout=5000",
"test:e2e:ui": "playwright test --ui --timeout=10000",
"test:e2e:demo": "playwright test --config=playwright.demo.config.ts --timeout=10000",
"screenshots": "playwright test --config=screenshots.playwright.config.ts --timeout=15000"
},
"dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "^1.1.3",
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
"@formkit/auto-animate": "^0.8.2",
"@tanstack/vue-query": "^5.32.0",
"@unovis/ts": "^1.4.1",
"@unovis/vue": "^1.4.1",
"@vee-validate/rules": "^4.12.8",
"@vee-validate/zod": "^4.12.8",
"@vueuse/core": "^10.10.0",
"add": "^2.0.6",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"date-fns": "^3.6.0",
"easymde": "^2.18.0",
"@tanstack/vue-query": "^5.80.10",
"@unovis/ts": "^1.5.2",
"@unovis/vue": "^1.5.2",
"@uppy/core": "^4.4.6",
"@uppy/dashboard": "^4.3.4",
"@uppy/drag-drop": "^4.1.3",
"@uppy/file-input": "^4.1.3",
"@uppy/progress-bar": "^4.2.1",
"@uppy/tus": "^4.2.2",
"@uppy/vue": "^2.2.0",
"@vueuse/core": "^13.4.0",
"caniuse-lite": "^1.0.30001723",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
"easymde": "^2.20.0",
"lodash.debounce": "^4.0.8",
"lodash.isequal": "^4.5.0",
"lucide-vue-next": "^0.365.0",
"marked": "^12.0.2",
"pinia": "^2.1.7",
"pocketbase": "^0.21.2",
"radix-vue": "^1.6.2",
"tailwind-merge": "^2.2.2",
"lucide-vue-next": "^0.475.0",
"pinia": "^3.0.3",
"radix-vue": "^1.9.17",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7",
"v-calendar": "^3.1.2",
"vee-validate": "^4.12.8",
"vue": "^3.4.21",
"vue-router": "^4.3.0",
"vue3-easymde": "^1.0.1",
"zod": "^3.23.8"
"vee-validate": "^4.15.1",
"vue": "^3.5.17",
"vue-router": "^4.5.1",
"vue3-easymde": "^1.0.1"
},
"devDependencies": {
"@openapitools/openapi-generator-cli": "^2.20.2",
"@playwright/test": "^1.53.1",
"@rushstack/eslint-patch": "^1.3.3",
"@tailwindcss/typography": "^0.5.13",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@tsconfig/node20": "^20.1.2",
"@tailwindcss/typography": "^0.5.16",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@tsconfig/node20": "^20.1.6",
"@types/lodash.debounce": "^4.0.9",
"@types/lodash.isequal": "^4.5.8",
"@types/node": "^20.11.28",
"@vitejs/plugin-vue": "^5.0.4",
"@types/node": "^24.0.3",
"@vitejs/plugin-vue": "^5.2.4",
"@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/tsconfig": "^0.5.1",
"autoprefixer": "^10.4.19",
"bun-types": "^1.1.6",
"@vue/tsconfig": "^0.7.0",
"autoprefixer": "^10.4.21",
"bun-types": "^1.2.16",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"npm-run-all2": "^6.1.2",
"prettier": "^3.0.3",
"prettier-plugin-tailwindcss": "^0.6.0",
"npm-run-all2": "^8.0.4",
"prettier": "^3.5.3",
"prettier-plugin-tailwindcss": "^0.6.12",
"tailwindcss": "^3.4.3",
"typescript": "~5.4.0",
"vite": "^5.1.6",
"vue-tsc": "^2.0.6"
"typescript": "~5.8.3",
"vite": "^6.3.5",
"vue-tsc": "^2.2.10"
}
}
}

21
ui/playwright.config.ts Normal file
View File

@@ -0,0 +1,21 @@
import { defineConfig, devices } from '@playwright/test'
export default defineConfig({
testDir: './tests/e2e',
fullyParallel: true,
webServer: {
command: 'make -C .. dev-upgrade',
port: 8090,
reuseExistingServer: !process.env.CI,
timeout: 120000, // 2 minutes timeout
},
use: {
baseURL: 'http://localhost:8090/ui/',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
})

View File

@@ -0,0 +1,21 @@
import { defineConfig, devices } from '@playwright/test'
export default defineConfig({
testDir: './tests/demo',
fullyParallel: true,
webServer: {
command: 'make -C .. dev-demo',
port: 8090,
reuseExistingServer: !process.env.CI,
timeout: 120000,
},
use: {
baseURL: 'http://localhost:8090/ui/',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
})

22
ui/screenshot.sh Normal file
View File

@@ -0,0 +1,22 @@
UI_DIR=$(dirname $0)
SCREENSHOT_DIR=../docs/screenshots/
cd ${UI_DIR}
bun screenshots
files=(
"dashboard.png"
"ticket.png"
"tasks.png"
"reactions.png"
)
for file in "${files[@]}"; do
echo "Processing ${file}..."
magick ${SCREENSHOT_DIR}${file} \
\( -size 1280x720 xc:none -fill white \
-draw "rectangle 0,0 1280,700 roundrectangle 0,700 1280,720 20,20" \) \
-alpha on -compose DstIn -composite "${SCREENSHOT_DIR}${file}"
magick "${SCREENSHOT_DIR}${file}" -crop 1280x719+0+0 +repage "${SCREENSHOT_DIR}${file}"
magick composite -geometry +56+91 "${SCREENSHOT_DIR}${file}" screenshots/frame.png "${SCREENSHOT_DIR}${file}"
done

View File

@@ -0,0 +1,22 @@
import { defineConfig, devices } from '@playwright/test'
export default defineConfig({
testDir: './screenshots',
fullyParallel: true,
webServer: {
command: 'make -C .. dev-10000',
port: 8090,
reuseExistingServer: !process.env.CI,
timeout: 120000,
stderr: 'ignore'
},
use: {
baseURL: 'http://localhost:8090/ui/',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
})

View File

@@ -0,0 +1,51 @@
import { test, expect } from '@playwright/test'
import { login, createTicket, createLink, createComment, createTimeline, createTask } from '../tests/e2e/util'
const screenshot = (name: string) => `../docs/screenshots/${name}.png`
const createFullTicket = async (page, name: string) => {
await createTicket(page, name)
await createLink(page, 'https://hr-portal.example.com', 'HR Portal Access Log')
await createTask(page, 'Review access logs for HR user', true)
await createTask(page, 'Interview HR staff involved', false)
await createComment(page, 'Suspicious login detected from unrecognized device in HR department')
await createComment(page, 'User reported unusual activity on their HR account')
await createTimeline(page, 'Security team notified and initial investigation started')
await createTimeline(page, 'Access to sensitive HR data temporarily restricted')
await createTimeline(page, 'Awaiting further analysis from IT forensics')
}
test('dashboard screenshot', async ({ page }) => {
await login(page, false)
await page.waitForTimeout(7000)
await page.screenshot({ path: screenshot('dashboard') })
})
test('ticket screenshot', async ({ page }) => {
await login(page, false)
const name = 'INCIDENT-1234'
await createFullTicket(page, name)
await page.getByText("Toggle Sidebar").click()
await page.waitForTimeout(7000)
await page.screenshot({ path: screenshot('ticket') })
})
test('tasks screenshot', async ({ page }) => {
await login(page, false)
const ticketName = 'INCIDENT-1234'
await createFullTicket(page, ticketName)
await createTask(page, 'Follow up with HR department', false)
await page.getByText("Toggle Sidebar").click()
await page.waitForTimeout(7000)
await page.screenshot({ path: screenshot('tasks') })
})
test('reactions screenshot', async ({ page }) => {
await login(page, false)
await page.goto('reactions')
await page.getByText('Assign new Tickets').click()
await expect(page.getByRole('heading', { name: 'Reactions' })).toBeVisible()
await page.getByText("Toggle Sidebar").click()
await page.waitForTimeout(7000)
await page.screenshot({ path: screenshot('reactions') })
})

BIN
ui/screenshots/frame.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

View File

@@ -1,5 +1,46 @@
<script setup lang="ts">
import Toaster from '@/components/ui/toast/Toaster.vue'
import { onMounted, watch } from 'vue'
import { RouterView } from 'vue-router'
import { useAuthStore } from '@/store/auth'
const authStore = useAuthStore()
const fetchUser = () => {
if (!authStore.token) {
authStore.setUser(undefined)
authStore.setPermissions([])
return
}
fetch('/auth/user', { headers: { Authorization: `Bearer ${authStore.token}` } }).then(
(response) => {
if (response.ok) {
response.json().then((user) => {
if (user) {
authStore.setUser(user.user)
authStore.setPermissions(user.permissions)
} else {
authStore.setUser(undefined)
authStore.setPermissions([])
}
})
}
}
)
}
onMounted(() => {
fetchUser()
})
watch(
() => authStore.token,
() => fetchUser(),
{ immediate: true }
)
</script>
<template>

16
ui/src/api.ts Normal file
View File

@@ -0,0 +1,16 @@
import { Configuration, DefaultApi } from '@/client'
import { useAuthStore } from '@/store/auth'
export function useAPI() {
const authStore = useAuthStore()
return new DefaultApi(
new Configuration({
basePath: 'http://localhost:8090/api',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `Bearer ${authStore.token}`
}
})
)
}

View File

@@ -33,6 +33,15 @@
--ring: 20 14.3% 4.1%;
--radius: 0.5rem;
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
--vis-tooltip-background-color: none !important;
--vis-tooltip-border-color: none !important;
--vis-tooltip-text-color: none !important;
@@ -75,6 +84,15 @@
--border: 12 6.5% 15.1%;
--input: 12 6.5% 15.1%;
--ring: 35.5 91.7% 32.9%;
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}

View File

@@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@@ -0,0 +1,57 @@
.openapi-generator-ignore
apis/DefaultApi.ts
apis/index.ts
index.ts
models/Comment.ts
models/CommentUpdate.ts
models/Config.ts
models/DashboardCounts.ts
models/EmailTemplate.ts
models/ExtendedComment.ts
models/ExtendedTask.ts
models/ExtendedTicket.ts
models/Feature.ts
models/FileUpdate.ts
models/Group.ts
models/GroupRelation.ts
models/GroupUpdate.ts
models/GroupUser.ts
models/Link.ts
models/LinkUpdate.ts
models/ModelError.ts
models/ModelFile.ts
models/NewComment.ts
models/NewFeature.ts
models/NewFile.ts
models/NewGroup.ts
models/NewLink.ts
models/NewReaction.ts
models/NewTask.ts
models/NewTicket.ts
models/NewTimelineEntry.ts
models/NewType.ts
models/NewUser.ts
models/NewWebhook.ts
models/Reaction.ts
models/ReactionUpdate.ts
models/Settings.ts
models/SettingsMeta.ts
models/SettingsSmtp.ts
models/Sidebar.ts
models/Table.ts
models/Task.ts
models/TaskUpdate.ts
models/Ticket.ts
models/TicketSearch.ts
models/TicketUpdate.ts
models/TimelineEntry.ts
models/TimelineEntryUpdate.ts
models/Type.ts
models/TypeUpdate.ts
models/User.ts
models/UserGroup.ts
models/UserUpdate.ts
models/Webhook.ts
models/WebhookUpdate.ts
models/index.ts
runtime.ts

View File

@@ -0,0 +1 @@
7.14.0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
/* tslint:disable */
/* eslint-disable */
export * from './DefaultApi'

5
ui/src/client/index.ts Normal file
View File

@@ -0,0 +1,5 @@
/* tslint:disable */
/* eslint-disable */
export * from './runtime'
export * from './apis/index'
export * from './models/index'

View File

@@ -0,0 +1,111 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface Comment
*/
export interface Comment {
/**
*
* @type {string}
* @memberof Comment
*/
id: string
/**
*
* @type {string}
* @memberof Comment
*/
ticket: string
/**
*
* @type {string}
* @memberof Comment
*/
author: string
/**
*
* @type {string}
* @memberof Comment
*/
message: string
/**
*
* @type {Date}
* @memberof Comment
*/
created: Date
/**
*
* @type {Date}
* @memberof Comment
*/
updated: Date
}
/**
* Check if a given object implements the Comment interface.
*/
export function instanceOfComment(value: object): value is Comment {
if (!('id' in value) || value['id'] === undefined) return false
if (!('ticket' in value) || value['ticket'] === undefined) return false
if (!('author' in value) || value['author'] === undefined) return false
if (!('message' in value) || value['message'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function CommentFromJSON(json: any): Comment {
return CommentFromJSONTyped(json, false)
}
export function CommentFromJSONTyped(json: any, ignoreDiscriminator: boolean): Comment {
if (json == null) {
return json
}
return {
id: json['id'],
ticket: json['ticket'],
author: json['author'],
message: json['message'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function CommentToJSON(json: any): Comment {
return CommentToJSONTyped(json, false)
}
export function CommentToJSONTyped(
value?: Comment | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
ticket: value['ticket'],
author: value['author'],
message: value['message'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,73 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface CommentUpdate
*/
export interface CommentUpdate {
/**
*
* @type {string}
* @memberof CommentUpdate
*/
author?: string
/**
*
* @type {string}
* @memberof CommentUpdate
*/
message?: string
}
/**
* Check if a given object implements the CommentUpdate interface.
*/
export function instanceOfCommentUpdate(value: object): value is CommentUpdate {
return true
}
export function CommentUpdateFromJSON(json: any): CommentUpdate {
return CommentUpdateFromJSONTyped(json, false)
}
export function CommentUpdateFromJSONTyped(json: any, ignoreDiscriminator: boolean): CommentUpdate {
if (json == null) {
return json
}
return {
author: json['author'] == null ? undefined : json['author'],
message: json['message'] == null ? undefined : json['message']
}
}
export function CommentUpdateToJSON(json: any): CommentUpdate {
return CommentUpdateToJSONTyped(json, false)
}
export function CommentUpdateToJSONTyped(
value?: CommentUpdate | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
author: value['author'],
message: value['message']
}
}

View File

@@ -0,0 +1,86 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
import type { Table } from './Table'
import { TableFromJSON, TableFromJSONTyped, TableToJSON, TableToJSONTyped } from './Table'
/**
*
* @export
* @interface Config
*/
export interface Config {
/**
*
* @type {Array<string>}
* @memberof Config
*/
flags: Array<string>
/**
*
* @type {Array<string>}
* @memberof Config
*/
permissions: Array<string>
/**
*
* @type {Array<Table>}
* @memberof Config
*/
tables: Array<Table>
}
/**
* Check if a given object implements the Config interface.
*/
export function instanceOfConfig(value: object): value is Config {
if (!('flags' in value) || value['flags'] === undefined) return false
if (!('permissions' in value) || value['permissions'] === undefined) return false
if (!('tables' in value) || value['tables'] === undefined) return false
return true
}
export function ConfigFromJSON(json: any): Config {
return ConfigFromJSONTyped(json, false)
}
export function ConfigFromJSONTyped(json: any, ignoreDiscriminator: boolean): Config {
if (json == null) {
return json
}
return {
flags: json['flags'],
permissions: json['permissions'],
tables: (json['tables'] as Array<any>).map(TableFromJSON)
}
}
export function ConfigToJSON(json: any): Config {
return ConfigToJSONTyped(json, false)
}
export function ConfigToJSONTyped(
value?: Config | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
flags: value['flags'],
permissions: value['permissions'],
tables: (value['tables'] as Array<any>).map(TableToJSON)
}
}

View File

@@ -0,0 +1,78 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface DashboardCounts
*/
export interface DashboardCounts {
/**
*
* @type {string}
* @memberof DashboardCounts
*/
id: string
/**
*
* @type {number}
* @memberof DashboardCounts
*/
count: number
}
/**
* Check if a given object implements the DashboardCounts interface.
*/
export function instanceOfDashboardCounts(value: object): value is DashboardCounts {
if (!('id' in value) || value['id'] === undefined) return false
if (!('count' in value) || value['count'] === undefined) return false
return true
}
export function DashboardCountsFromJSON(json: any): DashboardCounts {
return DashboardCountsFromJSONTyped(json, false)
}
export function DashboardCountsFromJSONTyped(
json: any,
ignoreDiscriminator: boolean
): DashboardCounts {
if (json == null) {
return json
}
return {
id: json['id'],
count: json['count']
}
}
export function DashboardCountsToJSON(json: any): DashboardCounts {
return DashboardCountsToJSONTyped(json, false)
}
export function DashboardCountsToJSONTyped(
value?: DashboardCounts | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
count: value['count']
}
}

View File

@@ -0,0 +1,75 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface EmailTemplate
*/
export interface EmailTemplate {
/**
*
* @type {string}
* @memberof EmailTemplate
*/
body: string
/**
*
* @type {string}
* @memberof EmailTemplate
*/
subject: string
}
/**
* Check if a given object implements the EmailTemplate interface.
*/
export function instanceOfEmailTemplate(value: object): value is EmailTemplate {
if (!('body' in value) || value['body'] === undefined) return false
if (!('subject' in value) || value['subject'] === undefined) return false
return true
}
export function EmailTemplateFromJSON(json: any): EmailTemplate {
return EmailTemplateFromJSONTyped(json, false)
}
export function EmailTemplateFromJSONTyped(json: any, ignoreDiscriminator: boolean): EmailTemplate {
if (json == null) {
return json
}
return {
body: json['body'],
subject: json['subject']
}
}
export function EmailTemplateToJSON(json: any): EmailTemplate {
return EmailTemplateToJSONTyped(json, false)
}
export function EmailTemplateToJSONTyped(
value?: EmailTemplate | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
body: value['body'],
subject: value['subject']
}
}

View File

@@ -0,0 +1,123 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface ExtendedComment
*/
export interface ExtendedComment {
/**
*
* @type {string}
* @memberof ExtendedComment
*/
id: string
/**
*
* @type {string}
* @memberof ExtendedComment
*/
ticket: string
/**
*
* @type {string}
* @memberof ExtendedComment
*/
author: string
/**
*
* @type {string}
* @memberof ExtendedComment
*/
message: string
/**
*
* @type {string}
* @memberof ExtendedComment
*/
authorName: string
/**
*
* @type {Date}
* @memberof ExtendedComment
*/
created: Date
/**
*
* @type {Date}
* @memberof ExtendedComment
*/
updated: Date
}
/**
* Check if a given object implements the ExtendedComment interface.
*/
export function instanceOfExtendedComment(value: object): value is ExtendedComment {
if (!('id' in value) || value['id'] === undefined) return false
if (!('ticket' in value) || value['ticket'] === undefined) return false
if (!('author' in value) || value['author'] === undefined) return false
if (!('message' in value) || value['message'] === undefined) return false
if (!('authorName' in value) || value['authorName'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function ExtendedCommentFromJSON(json: any): ExtendedComment {
return ExtendedCommentFromJSONTyped(json, false)
}
export function ExtendedCommentFromJSONTyped(
json: any,
ignoreDiscriminator: boolean
): ExtendedComment {
if (json == null) {
return json
}
return {
id: json['id'],
ticket: json['ticket'],
author: json['author'],
message: json['message'],
authorName: json['author_name'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function ExtendedCommentToJSON(json: any): ExtendedComment {
return ExtendedCommentToJSONTyped(json, false)
}
export function ExtendedCommentToJSONTyped(
value?: ExtendedComment | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
ticket: value['ticket'],
author: value['author'],
message: value['message'],
author_name: value['authorName'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,145 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface ExtendedTask
*/
export interface ExtendedTask {
/**
*
* @type {string}
* @memberof ExtendedTask
*/
id: string
/**
*
* @type {string}
* @memberof ExtendedTask
*/
ticket: string
/**
*
* @type {string}
* @memberof ExtendedTask
*/
name: string
/**
*
* @type {boolean}
* @memberof ExtendedTask
*/
open: boolean
/**
*
* @type {string}
* @memberof ExtendedTask
*/
owner?: string
/**
*
* @type {string}
* @memberof ExtendedTask
*/
ownerName?: string
/**
*
* @type {string}
* @memberof ExtendedTask
*/
ticketName: string
/**
*
* @type {string}
* @memberof ExtendedTask
*/
ticketType: string
/**
*
* @type {Date}
* @memberof ExtendedTask
*/
created: Date
/**
*
* @type {Date}
* @memberof ExtendedTask
*/
updated: Date
}
/**
* Check if a given object implements the ExtendedTask interface.
*/
export function instanceOfExtendedTask(value: object): value is ExtendedTask {
if (!('id' in value) || value['id'] === undefined) return false
if (!('ticket' in value) || value['ticket'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('open' in value) || value['open'] === undefined) return false
if (!('ticketName' in value) || value['ticketName'] === undefined) return false
if (!('ticketType' in value) || value['ticketType'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function ExtendedTaskFromJSON(json: any): ExtendedTask {
return ExtendedTaskFromJSONTyped(json, false)
}
export function ExtendedTaskFromJSONTyped(json: any, ignoreDiscriminator: boolean): ExtendedTask {
if (json == null) {
return json
}
return {
id: json['id'],
ticket: json['ticket'],
name: json['name'],
open: json['open'],
owner: json['owner'] == null ? undefined : json['owner'],
ownerName: json['owner_name'] == null ? undefined : json['owner_name'],
ticketName: json['ticket_name'],
ticketType: json['ticket_type'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function ExtendedTaskToJSON(json: any): ExtendedTask {
return ExtendedTaskToJSONTyped(json, false)
}
export function ExtendedTaskToJSONTyped(
value?: ExtendedTask | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
ticket: value['ticket'],
name: value['name'],
open: value['open'],
owner: value['owner'],
owner_name: value['ownerName'],
ticket_name: value['ticketName'],
ticket_type: value['ticketType'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,183 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface ExtendedTicket
*/
export interface ExtendedTicket {
/**
*
* @type {string}
* @memberof ExtendedTicket
*/
id: string
/**
*
* @type {string}
* @memberof ExtendedTicket
*/
type: string
/**
*
* @type {string}
* @memberof ExtendedTicket
*/
name: string
/**
*
* @type {string}
* @memberof ExtendedTicket
*/
description: string
/**
*
* @type {boolean}
* @memberof ExtendedTicket
*/
open: boolean
/**
*
* @type {string}
* @memberof ExtendedTicket
*/
owner?: string
/**
*
* @type {string}
* @memberof ExtendedTicket
*/
resolution?: string
/**
*
* @type {object}
* @memberof ExtendedTicket
*/
schema: object
/**
*
* @type {object}
* @memberof ExtendedTicket
*/
state: object
/**
*
* @type {string}
* @memberof ExtendedTicket
*/
ownerName?: string
/**
*
* @type {string}
* @memberof ExtendedTicket
*/
typeSingular: string
/**
*
* @type {string}
* @memberof ExtendedTicket
*/
typePlural: string
/**
*
* @type {Date}
* @memberof ExtendedTicket
*/
created: Date
/**
*
* @type {Date}
* @memberof ExtendedTicket
*/
updated: Date
}
/**
* Check if a given object implements the ExtendedTicket interface.
*/
export function instanceOfExtendedTicket(value: object): value is ExtendedTicket {
if (!('id' in value) || value['id'] === undefined) return false
if (!('type' in value) || value['type'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('description' in value) || value['description'] === undefined) return false
if (!('open' in value) || value['open'] === undefined) return false
if (!('schema' in value) || value['schema'] === undefined) return false
if (!('state' in value) || value['state'] === undefined) return false
if (!('typeSingular' in value) || value['typeSingular'] === undefined) return false
if (!('typePlural' in value) || value['typePlural'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function ExtendedTicketFromJSON(json: any): ExtendedTicket {
return ExtendedTicketFromJSONTyped(json, false)
}
export function ExtendedTicketFromJSONTyped(
json: any,
ignoreDiscriminator: boolean
): ExtendedTicket {
if (json == null) {
return json
}
return {
id: json['id'],
type: json['type'],
name: json['name'],
description: json['description'],
open: json['open'],
owner: json['owner'] == null ? undefined : json['owner'],
resolution: json['resolution'] == null ? undefined : json['resolution'],
schema: json['schema'],
state: json['state'],
ownerName: json['owner_name'] == null ? undefined : json['owner_name'],
typeSingular: json['type_singular'],
typePlural: json['type_plural'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function ExtendedTicketToJSON(json: any): ExtendedTicket {
return ExtendedTicketToJSONTyped(json, false)
}
export function ExtendedTicketToJSONTyped(
value?: ExtendedTicket | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
type: value['type'],
name: value['name'],
description: value['description'],
open: value['open'],
owner: value['owner'],
resolution: value['resolution'],
schema: value['schema'],
state: value['state'],
owner_name: value['ownerName'],
type_singular: value['typeSingular'],
type_plural: value['typePlural'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,93 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface Feature
*/
export interface Feature {
/**
*
* @type {string}
* @memberof Feature
*/
id: string
/**
*
* @type {string}
* @memberof Feature
*/
name: string
/**
*
* @type {Date}
* @memberof Feature
*/
created: Date
/**
*
* @type {Date}
* @memberof Feature
*/
updated: Date
}
/**
* Check if a given object implements the Feature interface.
*/
export function instanceOfFeature(value: object): value is Feature {
if (!('id' in value) || value['id'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function FeatureFromJSON(json: any): Feature {
return FeatureFromJSONTyped(json, false)
}
export function FeatureFromJSONTyped(json: any, ignoreDiscriminator: boolean): Feature {
if (json == null) {
return json
}
return {
id: json['id'],
name: json['name'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function FeatureToJSON(json: any): Feature {
return FeatureToJSONTyped(json, false)
}
export function FeatureToJSONTyped(
value?: Feature | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
name: value['name'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,65 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface FileUpdate
*/
export interface FileUpdate {
/**
*
* @type {string}
* @memberof FileUpdate
*/
name?: string
}
/**
* Check if a given object implements the FileUpdate interface.
*/
export function instanceOfFileUpdate(value: object): value is FileUpdate {
return true
}
export function FileUpdateFromJSON(json: any): FileUpdate {
return FileUpdateFromJSONTyped(json, false)
}
export function FileUpdateFromJSONTyped(json: any, ignoreDiscriminator: boolean): FileUpdate {
if (json == null) {
return json
}
return {
name: json['name'] == null ? undefined : json['name']
}
}
export function FileUpdateToJSON(json: any): FileUpdate {
return FileUpdateToJSONTyped(json, false)
}
export function FileUpdateToJSONTyped(
value?: FileUpdate | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
name: value['name']
}
}

View File

@@ -0,0 +1,99 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface Group
*/
export interface Group {
/**
*
* @type {string}
* @memberof Group
*/
id: string
/**
*
* @type {string}
* @memberof Group
*/
name: string
/**
*
* @type {Array<string>}
* @memberof Group
*/
permissions: Array<string>
/**
*
* @type {Date}
* @memberof Group
*/
created: Date
/**
*
* @type {Date}
* @memberof Group
*/
updated: Date
}
/**
* Check if a given object implements the Group interface.
*/
export function instanceOfGroup(value: object): value is Group {
if (!('id' in value) || value['id'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('permissions' in value) || value['permissions'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function GroupFromJSON(json: any): Group {
return GroupFromJSONTyped(json, false)
}
export function GroupFromJSONTyped(json: any, ignoreDiscriminator: boolean): Group {
if (json == null) {
return json
}
return {
id: json['id'],
name: json['name'],
permissions: json['permissions'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function GroupToJSON(json: any): Group {
return GroupToJSONTyped(json, false)
}
export function GroupToJSONTyped(value?: Group | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value
}
return {
id: value['id'],
name: value['name'],
permissions: value['permissions'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,66 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface GroupRelation
*/
export interface GroupRelation {
/**
*
* @type {string}
* @memberof GroupRelation
*/
groupId: string
}
/**
* Check if a given object implements the GroupRelation interface.
*/
export function instanceOfGroupRelation(value: object): value is GroupRelation {
if (!('groupId' in value) || value['groupId'] === undefined) return false
return true
}
export function GroupRelationFromJSON(json: any): GroupRelation {
return GroupRelationFromJSONTyped(json, false)
}
export function GroupRelationFromJSONTyped(json: any, ignoreDiscriminator: boolean): GroupRelation {
if (json == null) {
return json
}
return {
groupId: json['group_id']
}
}
export function GroupRelationToJSON(json: any): GroupRelation {
return GroupRelationToJSONTyped(json, false)
}
export function GroupRelationToJSONTyped(
value?: GroupRelation | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
group_id: value['groupId']
}
}

View File

@@ -0,0 +1,73 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface GroupUpdate
*/
export interface GroupUpdate {
/**
*
* @type {string}
* @memberof GroupUpdate
*/
name?: string
/**
*
* @type {Array<string>}
* @memberof GroupUpdate
*/
permissions?: Array<string>
}
/**
* Check if a given object implements the GroupUpdate interface.
*/
export function instanceOfGroupUpdate(value: object): value is GroupUpdate {
return true
}
export function GroupUpdateFromJSON(json: any): GroupUpdate {
return GroupUpdateFromJSONTyped(json, false)
}
export function GroupUpdateFromJSONTyped(json: any, ignoreDiscriminator: boolean): GroupUpdate {
if (json == null) {
return json
}
return {
name: json['name'] == null ? undefined : json['name'],
permissions: json['permissions'] == null ? undefined : json['permissions']
}
}
export function GroupUpdateToJSON(json: any): GroupUpdate {
return GroupUpdateToJSONTyped(json, false)
}
export function GroupUpdateToJSONTyped(
value?: GroupUpdate | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
name: value['name'],
permissions: value['permissions']
}
}

View File

@@ -0,0 +1,157 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface GroupUser
*/
export interface GroupUser {
/**
*
* @type {string}
* @memberof GroupUser
*/
id: string
/**
*
* @type {string}
* @memberof GroupUser
*/
username: string
/**
*
* @type {string}
* @memberof GroupUser
*/
avatar?: string
/**
*
* @type {string}
* @memberof GroupUser
*/
email?: string
/**
*
* @type {Date}
* @memberof GroupUser
*/
lastResetSentAt?: Date
/**
*
* @type {Date}
* @memberof GroupUser
*/
lastVerificationSentAt?: Date
/**
*
* @type {string}
* @memberof GroupUser
*/
name?: string
/**
*
* @type {boolean}
* @memberof GroupUser
*/
active: boolean
/**
*
* @type {string}
* @memberof GroupUser
*/
type: string
/**
*
* @type {Date}
* @memberof GroupUser
*/
created: Date
/**
*
* @type {Date}
* @memberof GroupUser
*/
updated: Date
}
/**
* Check if a given object implements the GroupUser interface.
*/
export function instanceOfGroupUser(value: object): value is GroupUser {
if (!('id' in value) || value['id'] === undefined) return false
if (!('username' in value) || value['username'] === undefined) return false
if (!('active' in value) || value['active'] === undefined) return false
if (!('type' in value) || value['type'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function GroupUserFromJSON(json: any): GroupUser {
return GroupUserFromJSONTyped(json, false)
}
export function GroupUserFromJSONTyped(json: any, ignoreDiscriminator: boolean): GroupUser {
if (json == null) {
return json
}
return {
id: json['id'],
username: json['username'],
avatar: json['avatar'] == null ? undefined : json['avatar'],
email: json['email'] == null ? undefined : json['email'],
lastResetSentAt:
json['lastResetSentAt'] == null ? undefined : new Date(json['lastResetSentAt']),
lastVerificationSentAt:
json['lastVerificationSentAt'] == null ? undefined : new Date(json['lastVerificationSentAt']),
name: json['name'] == null ? undefined : json['name'],
active: json['active'],
type: json['type'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function GroupUserToJSON(json: any): GroupUser {
return GroupUserToJSONTyped(json, false)
}
export function GroupUserToJSONTyped(
value?: GroupUser | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
username: value['username'],
avatar: value['avatar'],
email: value['email'],
lastResetSentAt:
value['lastResetSentAt'] == null ? undefined : value['lastResetSentAt'].toISOString(),
lastVerificationSentAt:
value['lastVerificationSentAt'] == null
? undefined
: value['lastVerificationSentAt'].toISOString(),
name: value['name'],
active: value['active'],
type: value['type'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,108 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface Link
*/
export interface Link {
/**
*
* @type {string}
* @memberof Link
*/
id: string
/**
*
* @type {string}
* @memberof Link
*/
ticket: string
/**
*
* @type {string}
* @memberof Link
*/
name: string
/**
*
* @type {string}
* @memberof Link
*/
url: string
/**
*
* @type {Date}
* @memberof Link
*/
created: Date
/**
*
* @type {Date}
* @memberof Link
*/
updated: Date
}
/**
* Check if a given object implements the Link interface.
*/
export function instanceOfLink(value: object): value is Link {
if (!('id' in value) || value['id'] === undefined) return false
if (!('ticket' in value) || value['ticket'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('url' in value) || value['url'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function LinkFromJSON(json: any): Link {
return LinkFromJSONTyped(json, false)
}
export function LinkFromJSONTyped(json: any, ignoreDiscriminator: boolean): Link {
if (json == null) {
return json
}
return {
id: json['id'],
ticket: json['ticket'],
name: json['name'],
url: json['url'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function LinkToJSON(json: any): Link {
return LinkToJSONTyped(json, false)
}
export function LinkToJSONTyped(value?: Link | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value
}
return {
id: value['id'],
ticket: value['ticket'],
name: value['name'],
url: value['url'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,73 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface LinkUpdate
*/
export interface LinkUpdate {
/**
*
* @type {string}
* @memberof LinkUpdate
*/
name?: string
/**
*
* @type {string}
* @memberof LinkUpdate
*/
url?: string
}
/**
* Check if a given object implements the LinkUpdate interface.
*/
export function instanceOfLinkUpdate(value: object): value is LinkUpdate {
return true
}
export function LinkUpdateFromJSON(json: any): LinkUpdate {
return LinkUpdateFromJSONTyped(json, false)
}
export function LinkUpdateFromJSONTyped(json: any, ignoreDiscriminator: boolean): LinkUpdate {
if (json == null) {
return json
}
return {
name: json['name'] == null ? undefined : json['name'],
url: json['url'] == null ? undefined : json['url']
}
}
export function LinkUpdateToJSON(json: any): LinkUpdate {
return LinkUpdateToJSONTyped(json, false)
}
export function LinkUpdateToJSONTyped(
value?: LinkUpdate | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
name: value['name'],
url: value['url']
}
}

View File

@@ -0,0 +1,84 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface ModelError
*/
export interface ModelError {
/**
*
* @type {number}
* @memberof ModelError
*/
status: number
/**
*
* @type {string}
* @memberof ModelError
*/
error: string
/**
*
* @type {string}
* @memberof ModelError
*/
message: string
}
/**
* Check if a given object implements the ModelError interface.
*/
export function instanceOfModelError(value: object): value is ModelError {
if (!('status' in value) || value['status'] === undefined) return false
if (!('error' in value) || value['error'] === undefined) return false
if (!('message' in value) || value['message'] === undefined) return false
return true
}
export function ModelErrorFromJSON(json: any): ModelError {
return ModelErrorFromJSONTyped(json, false)
}
export function ModelErrorFromJSONTyped(json: any, ignoreDiscriminator: boolean): ModelError {
if (json == null) {
return json
}
return {
status: json['status'],
error: json['error'],
message: json['message']
}
}
export function ModelErrorToJSON(json: any): ModelError {
return ModelErrorToJSONTyped(json, false)
}
export function ModelErrorToJSONTyped(
value?: ModelError | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
status: value['status'],
error: value['error'],
message: value['message']
}
}

View File

@@ -0,0 +1,111 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface ModelFile
*/
export interface ModelFile {
/**
*
* @type {string}
* @memberof ModelFile
*/
id: string
/**
*
* @type {string}
* @memberof ModelFile
*/
ticket: string
/**
*
* @type {string}
* @memberof ModelFile
*/
name: string
/**
*
* @type {number}
* @memberof ModelFile
*/
size: number
/**
*
* @type {Date}
* @memberof ModelFile
*/
created: Date
/**
*
* @type {Date}
* @memberof ModelFile
*/
updated: Date
}
/**
* Check if a given object implements the ModelFile interface.
*/
export function instanceOfModelFile(value: object): value is ModelFile {
if (!('id' in value) || value['id'] === undefined) return false
if (!('ticket' in value) || value['ticket'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('size' in value) || value['size'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function ModelFileFromJSON(json: any): ModelFile {
return ModelFileFromJSONTyped(json, false)
}
export function ModelFileFromJSONTyped(json: any, ignoreDiscriminator: boolean): ModelFile {
if (json == null) {
return json
}
return {
id: json['id'],
ticket: json['ticket'],
name: json['name'],
size: json['size'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function ModelFileToJSON(json: any): ModelFile {
return ModelFileToJSONTyped(json, false)
}
export function ModelFileToJSONTyped(
value?: ModelFile | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
ticket: value['ticket'],
name: value['name'],
size: value['size'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,84 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface NewComment
*/
export interface NewComment {
/**
*
* @type {string}
* @memberof NewComment
*/
ticket: string
/**
*
* @type {string}
* @memberof NewComment
*/
author: string
/**
*
* @type {string}
* @memberof NewComment
*/
message: string
}
/**
* Check if a given object implements the NewComment interface.
*/
export function instanceOfNewComment(value: object): value is NewComment {
if (!('ticket' in value) || value['ticket'] === undefined) return false
if (!('author' in value) || value['author'] === undefined) return false
if (!('message' in value) || value['message'] === undefined) return false
return true
}
export function NewCommentFromJSON(json: any): NewComment {
return NewCommentFromJSONTyped(json, false)
}
export function NewCommentFromJSONTyped(json: any, ignoreDiscriminator: boolean): NewComment {
if (json == null) {
return json
}
return {
ticket: json['ticket'],
author: json['author'],
message: json['message']
}
}
export function NewCommentToJSON(json: any): NewComment {
return NewCommentToJSONTyped(json, false)
}
export function NewCommentToJSONTyped(
value?: NewComment | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
ticket: value['ticket'],
author: value['author'],
message: value['message']
}
}

View File

@@ -0,0 +1,66 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface NewFeature
*/
export interface NewFeature {
/**
*
* @type {string}
* @memberof NewFeature
*/
name: string
}
/**
* Check if a given object implements the NewFeature interface.
*/
export function instanceOfNewFeature(value: object): value is NewFeature {
if (!('name' in value) || value['name'] === undefined) return false
return true
}
export function NewFeatureFromJSON(json: any): NewFeature {
return NewFeatureFromJSONTyped(json, false)
}
export function NewFeatureFromJSONTyped(json: any, ignoreDiscriminator: boolean): NewFeature {
if (json == null) {
return json
}
return {
name: json['name']
}
}
export function NewFeatureToJSON(json: any): NewFeature {
return NewFeatureToJSONTyped(json, false)
}
export function NewFeatureToJSONTyped(
value?: NewFeature | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
name: value['name']
}
}

View File

@@ -0,0 +1,84 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface NewFile
*/
export interface NewFile {
/**
*
* @type {string}
* @memberof NewFile
*/
ticket: string
/**
*
* @type {string}
* @memberof NewFile
*/
blob: string
/**
*
* @type {string}
* @memberof NewFile
*/
name: string
}
/**
* Check if a given object implements the NewFile interface.
*/
export function instanceOfNewFile(value: object): value is NewFile {
if (!('ticket' in value) || value['ticket'] === undefined) return false
if (!('blob' in value) || value['blob'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
return true
}
export function NewFileFromJSON(json: any): NewFile {
return NewFileFromJSONTyped(json, false)
}
export function NewFileFromJSONTyped(json: any, ignoreDiscriminator: boolean): NewFile {
if (json == null) {
return json
}
return {
ticket: json['ticket'],
blob: json['blob'],
name: json['name']
}
}
export function NewFileToJSON(json: any): NewFile {
return NewFileToJSONTyped(json, false)
}
export function NewFileToJSONTyped(
value?: NewFile | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
ticket: value['ticket'],
blob: value['blob'],
name: value['name']
}
}

View File

@@ -0,0 +1,75 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface NewGroup
*/
export interface NewGroup {
/**
*
* @type {string}
* @memberof NewGroup
*/
name: string
/**
*
* @type {Array<string>}
* @memberof NewGroup
*/
permissions: Array<string>
}
/**
* Check if a given object implements the NewGroup interface.
*/
export function instanceOfNewGroup(value: object): value is NewGroup {
if (!('name' in value) || value['name'] === undefined) return false
if (!('permissions' in value) || value['permissions'] === undefined) return false
return true
}
export function NewGroupFromJSON(json: any): NewGroup {
return NewGroupFromJSONTyped(json, false)
}
export function NewGroupFromJSONTyped(json: any, ignoreDiscriminator: boolean): NewGroup {
if (json == null) {
return json
}
return {
name: json['name'],
permissions: json['permissions']
}
}
export function NewGroupToJSON(json: any): NewGroup {
return NewGroupToJSONTyped(json, false)
}
export function NewGroupToJSONTyped(
value?: NewGroup | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
name: value['name'],
permissions: value['permissions']
}
}

View File

@@ -0,0 +1,84 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface NewLink
*/
export interface NewLink {
/**
*
* @type {string}
* @memberof NewLink
*/
ticket: string
/**
*
* @type {string}
* @memberof NewLink
*/
name: string
/**
*
* @type {string}
* @memberof NewLink
*/
url: string
}
/**
* Check if a given object implements the NewLink interface.
*/
export function instanceOfNewLink(value: object): value is NewLink {
if (!('ticket' in value) || value['ticket'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('url' in value) || value['url'] === undefined) return false
return true
}
export function NewLinkFromJSON(json: any): NewLink {
return NewLinkFromJSONTyped(json, false)
}
export function NewLinkFromJSONTyped(json: any, ignoreDiscriminator: boolean): NewLink {
if (json == null) {
return json
}
return {
ticket: json['ticket'],
name: json['name'],
url: json['url']
}
}
export function NewLinkToJSON(json: any): NewLink {
return NewLinkToJSONTyped(json, false)
}
export function NewLinkToJSONTyped(
value?: NewLink | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
ticket: value['ticket'],
name: value['name'],
url: value['url']
}
}

View File

@@ -0,0 +1,102 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface NewReaction
*/
export interface NewReaction {
/**
*
* @type {string}
* @memberof NewReaction
*/
name: string
/**
*
* @type {string}
* @memberof NewReaction
*/
action: string
/**
*
* @type {object}
* @memberof NewReaction
*/
actiondata: object
/**
*
* @type {string}
* @memberof NewReaction
*/
trigger: string
/**
*
* @type {object}
* @memberof NewReaction
*/
triggerdata: object
}
/**
* Check if a given object implements the NewReaction interface.
*/
export function instanceOfNewReaction(value: object): value is NewReaction {
if (!('name' in value) || value['name'] === undefined) return false
if (!('action' in value) || value['action'] === undefined) return false
if (!('actiondata' in value) || value['actiondata'] === undefined) return false
if (!('trigger' in value) || value['trigger'] === undefined) return false
if (!('triggerdata' in value) || value['triggerdata'] === undefined) return false
return true
}
export function NewReactionFromJSON(json: any): NewReaction {
return NewReactionFromJSONTyped(json, false)
}
export function NewReactionFromJSONTyped(json: any, ignoreDiscriminator: boolean): NewReaction {
if (json == null) {
return json
}
return {
name: json['name'],
action: json['action'],
actiondata: json['actiondata'],
trigger: json['trigger'],
triggerdata: json['triggerdata']
}
}
export function NewReactionToJSON(json: any): NewReaction {
return NewReactionToJSONTyped(json, false)
}
export function NewReactionToJSONTyped(
value?: NewReaction | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
name: value['name'],
action: value['action'],
actiondata: value['actiondata'],
trigger: value['trigger'],
triggerdata: value['triggerdata']
}
}

View File

@@ -0,0 +1,92 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface NewTask
*/
export interface NewTask {
/**
*
* @type {string}
* @memberof NewTask
*/
ticket: string
/**
*
* @type {string}
* @memberof NewTask
*/
name: string
/**
*
* @type {boolean}
* @memberof NewTask
*/
open: boolean
/**
*
* @type {string}
* @memberof NewTask
*/
owner?: string
}
/**
* Check if a given object implements the NewTask interface.
*/
export function instanceOfNewTask(value: object): value is NewTask {
if (!('ticket' in value) || value['ticket'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('open' in value) || value['open'] === undefined) return false
return true
}
export function NewTaskFromJSON(json: any): NewTask {
return NewTaskFromJSONTyped(json, false)
}
export function NewTaskFromJSONTyped(json: any, ignoreDiscriminator: boolean): NewTask {
if (json == null) {
return json
}
return {
ticket: json['ticket'],
name: json['name'],
open: json['open'],
owner: json['owner'] == null ? undefined : json['owner']
}
}
export function NewTaskToJSON(json: any): NewTask {
return NewTaskToJSONTyped(json, false)
}
export function NewTaskToJSONTyped(
value?: NewTask | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
ticket: value['ticket'],
name: value['name'],
open: value['open'],
owner: value['owner']
}
}

View File

@@ -0,0 +1,127 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface NewTicket
*/
export interface NewTicket {
/**
*
* @type {string}
* @memberof NewTicket
*/
type: string
/**
*
* @type {string}
* @memberof NewTicket
*/
name: string
/**
*
* @type {string}
* @memberof NewTicket
*/
description: string
/**
*
* @type {boolean}
* @memberof NewTicket
*/
open: boolean
/**
*
* @type {string}
* @memberof NewTicket
*/
owner?: string
/**
*
* @type {string}
* @memberof NewTicket
*/
resolution?: string
/**
*
* @type {object}
* @memberof NewTicket
*/
schema: object
/**
*
* @type {object}
* @memberof NewTicket
*/
state: object
}
/**
* Check if a given object implements the NewTicket interface.
*/
export function instanceOfNewTicket(value: object): value is NewTicket {
if (!('type' in value) || value['type'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('description' in value) || value['description'] === undefined) return false
if (!('open' in value) || value['open'] === undefined) return false
if (!('schema' in value) || value['schema'] === undefined) return false
if (!('state' in value) || value['state'] === undefined) return false
return true
}
export function NewTicketFromJSON(json: any): NewTicket {
return NewTicketFromJSONTyped(json, false)
}
export function NewTicketFromJSONTyped(json: any, ignoreDiscriminator: boolean): NewTicket {
if (json == null) {
return json
}
return {
type: json['type'],
name: json['name'],
description: json['description'],
open: json['open'],
owner: json['owner'] == null ? undefined : json['owner'],
resolution: json['resolution'] == null ? undefined : json['resolution'],
schema: json['schema'],
state: json['state']
}
}
export function NewTicketToJSON(json: any): NewTicket {
return NewTicketToJSONTyped(json, false)
}
export function NewTicketToJSONTyped(
value?: NewTicket | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
type: value['type'],
name: value['name'],
description: value['description'],
open: value['open'],
owner: value['owner'],
resolution: value['resolution'],
schema: value['schema'],
state: value['state']
}
}

View File

@@ -0,0 +1,87 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface NewTimelineEntry
*/
export interface NewTimelineEntry {
/**
*
* @type {string}
* @memberof NewTimelineEntry
*/
ticket: string
/**
*
* @type {string}
* @memberof NewTimelineEntry
*/
message: string
/**
*
* @type {Date}
* @memberof NewTimelineEntry
*/
time: Date
}
/**
* Check if a given object implements the NewTimelineEntry interface.
*/
export function instanceOfNewTimelineEntry(value: object): value is NewTimelineEntry {
if (!('ticket' in value) || value['ticket'] === undefined) return false
if (!('message' in value) || value['message'] === undefined) return false
if (!('time' in value) || value['time'] === undefined) return false
return true
}
export function NewTimelineEntryFromJSON(json: any): NewTimelineEntry {
return NewTimelineEntryFromJSONTyped(json, false)
}
export function NewTimelineEntryFromJSONTyped(
json: any,
ignoreDiscriminator: boolean
): NewTimelineEntry {
if (json == null) {
return json
}
return {
ticket: json['ticket'],
message: json['message'],
time: new Date(json['time'])
}
}
export function NewTimelineEntryToJSON(json: any): NewTimelineEntry {
return NewTimelineEntryToJSONTyped(json, false)
}
export function NewTimelineEntryToJSONTyped(
value?: NewTimelineEntry | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
ticket: value['ticket'],
message: value['message'],
time: value['time'].toISOString()
}
}

View File

@@ -0,0 +1,92 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface NewType
*/
export interface NewType {
/**
*
* @type {string}
* @memberof NewType
*/
icon?: string
/**
*
* @type {string}
* @memberof NewType
*/
plural: string
/**
*
* @type {object}
* @memberof NewType
*/
schema: object
/**
*
* @type {string}
* @memberof NewType
*/
singular: string
}
/**
* Check if a given object implements the NewType interface.
*/
export function instanceOfNewType(value: object): value is NewType {
if (!('plural' in value) || value['plural'] === undefined) return false
if (!('schema' in value) || value['schema'] === undefined) return false
if (!('singular' in value) || value['singular'] === undefined) return false
return true
}
export function NewTypeFromJSON(json: any): NewType {
return NewTypeFromJSONTyped(json, false)
}
export function NewTypeFromJSONTyped(json: any, ignoreDiscriminator: boolean): NewType {
if (json == null) {
return json
}
return {
icon: json['icon'] == null ? undefined : json['icon'],
plural: json['plural'],
schema: json['schema'],
singular: json['singular']
}
}
export function NewTypeToJSON(json: any): NewType {
return NewTypeToJSONTyped(json, false)
}
export function NewTypeToJSONTyped(
value?: NewType | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
icon: value['icon'],
plural: value['plural'],
schema: value['schema'],
singular: value['singular']
}
}

View File

@@ -0,0 +1,99 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface NewUser
*/
export interface NewUser {
/**
*
* @type {string}
* @memberof NewUser
*/
username: string
/**
*
* @type {string}
* @memberof NewUser
*/
avatar?: string
/**
*
* @type {string}
* @memberof NewUser
*/
email?: string
/**
*
* @type {string}
* @memberof NewUser
*/
name?: string
/**
*
* @type {boolean}
* @memberof NewUser
*/
active: boolean
}
/**
* Check if a given object implements the NewUser interface.
*/
export function instanceOfNewUser(value: object): value is NewUser {
if (!('username' in value) || value['username'] === undefined) return false
if (!('active' in value) || value['active'] === undefined) return false
return true
}
export function NewUserFromJSON(json: any): NewUser {
return NewUserFromJSONTyped(json, false)
}
export function NewUserFromJSONTyped(json: any, ignoreDiscriminator: boolean): NewUser {
if (json == null) {
return json
}
return {
username: json['username'],
avatar: json['avatar'] == null ? undefined : json['avatar'],
email: json['email'] == null ? undefined : json['email'],
name: json['name'] == null ? undefined : json['name'],
active: json['active']
}
}
export function NewUserToJSON(json: any): NewUser {
return NewUserToJSONTyped(json, false)
}
export function NewUserToJSONTyped(
value?: NewUser | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
username: value['username'],
avatar: value['avatar'],
email: value['email'],
name: value['name'],
active: value['active']
}
}

View File

@@ -0,0 +1,84 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface NewWebhook
*/
export interface NewWebhook {
/**
*
* @type {string}
* @memberof NewWebhook
*/
name: string
/**
*
* @type {string}
* @memberof NewWebhook
*/
collection: string
/**
*
* @type {string}
* @memberof NewWebhook
*/
destination: string
}
/**
* Check if a given object implements the NewWebhook interface.
*/
export function instanceOfNewWebhook(value: object): value is NewWebhook {
if (!('name' in value) || value['name'] === undefined) return false
if (!('collection' in value) || value['collection'] === undefined) return false
if (!('destination' in value) || value['destination'] === undefined) return false
return true
}
export function NewWebhookFromJSON(json: any): NewWebhook {
return NewWebhookFromJSONTyped(json, false)
}
export function NewWebhookFromJSONTyped(json: any, ignoreDiscriminator: boolean): NewWebhook {
if (json == null) {
return json
}
return {
name: json['name'],
collection: json['collection'],
destination: json['destination']
}
}
export function NewWebhookToJSON(json: any): NewWebhook {
return NewWebhookToJSONTyped(json, false)
}
export function NewWebhookToJSONTyped(
value?: NewWebhook | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
name: value['name'],
collection: value['collection'],
destination: value['destination']
}
}

View File

@@ -0,0 +1,129 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface Reaction
*/
export interface Reaction {
/**
*
* @type {string}
* @memberof Reaction
*/
id: string
/**
*
* @type {string}
* @memberof Reaction
*/
name: string
/**
*
* @type {string}
* @memberof Reaction
*/
action: string
/**
*
* @type {object}
* @memberof Reaction
*/
actiondata: object
/**
*
* @type {string}
* @memberof Reaction
*/
trigger: string
/**
*
* @type {object}
* @memberof Reaction
*/
triggerdata: object
/**
*
* @type {Date}
* @memberof Reaction
*/
created: Date
/**
*
* @type {Date}
* @memberof Reaction
*/
updated: Date
}
/**
* Check if a given object implements the Reaction interface.
*/
export function instanceOfReaction(value: object): value is Reaction {
if (!('id' in value) || value['id'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('action' in value) || value['action'] === undefined) return false
if (!('actiondata' in value) || value['actiondata'] === undefined) return false
if (!('trigger' in value) || value['trigger'] === undefined) return false
if (!('triggerdata' in value) || value['triggerdata'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function ReactionFromJSON(json: any): Reaction {
return ReactionFromJSONTyped(json, false)
}
export function ReactionFromJSONTyped(json: any, ignoreDiscriminator: boolean): Reaction {
if (json == null) {
return json
}
return {
id: json['id'],
name: json['name'],
action: json['action'],
actiondata: json['actiondata'],
trigger: json['trigger'],
triggerdata: json['triggerdata'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function ReactionToJSON(json: any): Reaction {
return ReactionToJSONTyped(json, false)
}
export function ReactionToJSONTyped(
value?: Reaction | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
name: value['name'],
action: value['action'],
actiondata: value['actiondata'],
trigger: value['trigger'],
triggerdata: value['triggerdata'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,100 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface ReactionUpdate
*/
export interface ReactionUpdate {
/**
*
* @type {string}
* @memberof ReactionUpdate
*/
name?: string
/**
*
* @type {string}
* @memberof ReactionUpdate
*/
action?: string
/**
*
* @type {object}
* @memberof ReactionUpdate
*/
actiondata?: object
/**
*
* @type {string}
* @memberof ReactionUpdate
*/
trigger?: string
/**
*
* @type {object}
* @memberof ReactionUpdate
*/
triggerdata?: object
}
/**
* Check if a given object implements the ReactionUpdate interface.
*/
export function instanceOfReactionUpdate(value: object): value is ReactionUpdate {
return true
}
export function ReactionUpdateFromJSON(json: any): ReactionUpdate {
return ReactionUpdateFromJSONTyped(json, false)
}
export function ReactionUpdateFromJSONTyped(
json: any,
ignoreDiscriminator: boolean
): ReactionUpdate {
if (json == null) {
return json
}
return {
name: json['name'] == null ? undefined : json['name'],
action: json['action'] == null ? undefined : json['action'],
actiondata: json['actiondata'] == null ? undefined : json['actiondata'],
trigger: json['trigger'] == null ? undefined : json['trigger'],
triggerdata: json['triggerdata'] == null ? undefined : json['triggerdata']
}
}
export function ReactionUpdateToJSON(json: any): ReactionUpdate {
return ReactionUpdateToJSONTyped(json, false)
}
export function ReactionUpdateToJSONTyped(
value?: ReactionUpdate | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
name: value['name'],
action: value['action'],
actiondata: value['actiondata'],
trigger: value['trigger'],
triggerdata: value['triggerdata']
}
}

View File

@@ -0,0 +1,89 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
import type { SettingsMeta } from './SettingsMeta'
import {
SettingsMetaFromJSON,
SettingsMetaFromJSONTyped,
SettingsMetaToJSON,
SettingsMetaToJSONTyped
} from './SettingsMeta'
import type { SettingsSmtp } from './SettingsSmtp'
import {
SettingsSmtpFromJSON,
SettingsSmtpFromJSONTyped,
SettingsSmtpToJSON,
SettingsSmtpToJSONTyped
} from './SettingsSmtp'
/**
*
* @export
* @interface Settings
*/
export interface Settings {
/**
*
* @type {SettingsMeta}
* @memberof Settings
*/
meta: SettingsMeta
/**
*
* @type {SettingsSmtp}
* @memberof Settings
*/
smtp: SettingsSmtp
}
/**
* Check if a given object implements the Settings interface.
*/
export function instanceOfSettings(value: object): value is Settings {
if (!('meta' in value) || value['meta'] === undefined) return false
if (!('smtp' in value) || value['smtp'] === undefined) return false
return true
}
export function SettingsFromJSON(json: any): Settings {
return SettingsFromJSONTyped(json, false)
}
export function SettingsFromJSONTyped(json: any, ignoreDiscriminator: boolean): Settings {
if (json == null) {
return json
}
return {
meta: SettingsMetaFromJSON(json['meta']),
smtp: SettingsSmtpFromJSON(json['smtp'])
}
}
export function SettingsToJSON(json: any): Settings {
return SettingsToJSONTyped(json, false)
}
export function SettingsToJSONTyped(
value?: Settings | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
meta: SettingsMetaToJSON(value['meta']),
smtp: SettingsSmtpToJSON(value['smtp'])
}
}

View File

@@ -0,0 +1,110 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
import type { EmailTemplate } from './EmailTemplate'
import {
EmailTemplateFromJSON,
EmailTemplateFromJSONTyped,
EmailTemplateToJSON,
EmailTemplateToJSONTyped
} from './EmailTemplate'
/**
*
* @export
* @interface SettingsMeta
*/
export interface SettingsMeta {
/**
*
* @type {string}
* @memberof SettingsMeta
*/
appName: string
/**
*
* @type {string}
* @memberof SettingsMeta
*/
appUrl: string
/**
*
* @type {string}
* @memberof SettingsMeta
*/
senderName: string
/**
*
* @type {string}
* @memberof SettingsMeta
*/
senderAddress: string
/**
*
* @type {EmailTemplate}
* @memberof SettingsMeta
*/
resetPasswordTemplate: EmailTemplate
}
/**
* Check if a given object implements the SettingsMeta interface.
*/
export function instanceOfSettingsMeta(value: object): value is SettingsMeta {
if (!('appName' in value) || value['appName'] === undefined) return false
if (!('appUrl' in value) || value['appUrl'] === undefined) return false
if (!('senderName' in value) || value['senderName'] === undefined) return false
if (!('senderAddress' in value) || value['senderAddress'] === undefined) return false
if (!('resetPasswordTemplate' in value) || value['resetPasswordTemplate'] === undefined)
return false
return true
}
export function SettingsMetaFromJSON(json: any): SettingsMeta {
return SettingsMetaFromJSONTyped(json, false)
}
export function SettingsMetaFromJSONTyped(json: any, ignoreDiscriminator: boolean): SettingsMeta {
if (json == null) {
return json
}
return {
appName: json['app_name'],
appUrl: json['app_url'],
senderName: json['sender_name'],
senderAddress: json['sender_address'],
resetPasswordTemplate: EmailTemplateFromJSON(json['reset_password_template'])
}
}
export function SettingsMetaToJSON(json: any): SettingsMeta {
return SettingsMetaToJSONTyped(json, false)
}
export function SettingsMetaToJSONTyped(
value?: SettingsMeta | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
app_name: value['appName'],
app_url: value['appUrl'],
sender_name: value['senderName'],
sender_address: value['senderAddress'],
reset_password_template: EmailTemplateToJSON(value['resetPasswordTemplate'])
}
}

View File

@@ -0,0 +1,129 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface SettingsSmtp
*/
export interface SettingsSmtp {
/**
*
* @type {boolean}
* @memberof SettingsSmtp
*/
enabled: boolean
/**
*
* @type {string}
* @memberof SettingsSmtp
*/
host: string
/**
*
* @type {number}
* @memberof SettingsSmtp
*/
port: number
/**
*
* @type {string}
* @memberof SettingsSmtp
*/
username: string
/**
*
* @type {string}
* @memberof SettingsSmtp
*/
password: string
/**
*
* @type {string}
* @memberof SettingsSmtp
*/
authMethod: string
/**
*
* @type {boolean}
* @memberof SettingsSmtp
*/
tls: boolean
/**
*
* @type {string}
* @memberof SettingsSmtp
*/
localName: string
}
/**
* Check if a given object implements the SettingsSmtp interface.
*/
export function instanceOfSettingsSmtp(value: object): value is SettingsSmtp {
if (!('enabled' in value) || value['enabled'] === undefined) return false
if (!('host' in value) || value['host'] === undefined) return false
if (!('port' in value) || value['port'] === undefined) return false
if (!('username' in value) || value['username'] === undefined) return false
if (!('password' in value) || value['password'] === undefined) return false
if (!('authMethod' in value) || value['authMethod'] === undefined) return false
if (!('tls' in value) || value['tls'] === undefined) return false
if (!('localName' in value) || value['localName'] === undefined) return false
return true
}
export function SettingsSmtpFromJSON(json: any): SettingsSmtp {
return SettingsSmtpFromJSONTyped(json, false)
}
export function SettingsSmtpFromJSONTyped(json: any, ignoreDiscriminator: boolean): SettingsSmtp {
if (json == null) {
return json
}
return {
enabled: json['enabled'],
host: json['host'],
port: json['port'],
username: json['username'],
password: json['password'],
authMethod: json['auth_method'],
tls: json['tls'],
localName: json['local_name']
}
}
export function SettingsSmtpToJSON(json: any): SettingsSmtp {
return SettingsSmtpToJSONTyped(json, false)
}
export function SettingsSmtpToJSONTyped(
value?: SettingsSmtp | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
enabled: value['enabled'],
host: value['host'],
port: value['port'],
username: value['username'],
password: value['password'],
auth_method: value['authMethod'],
tls: value['tls'],
local_name: value['localName']
}
}

View File

@@ -0,0 +1,101 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface Sidebar
*/
export interface Sidebar {
/**
*
* @type {string}
* @memberof Sidebar
*/
id: string
/**
*
* @type {string}
* @memberof Sidebar
*/
singular: string
/**
*
* @type {string}
* @memberof Sidebar
*/
plural: string
/**
*
* @type {string}
* @memberof Sidebar
*/
icon?: string
/**
*
* @type {number}
* @memberof Sidebar
*/
count: number
}
/**
* Check if a given object implements the Sidebar interface.
*/
export function instanceOfSidebar(value: object): value is Sidebar {
if (!('id' in value) || value['id'] === undefined) return false
if (!('singular' in value) || value['singular'] === undefined) return false
if (!('plural' in value) || value['plural'] === undefined) return false
if (!('count' in value) || value['count'] === undefined) return false
return true
}
export function SidebarFromJSON(json: any): Sidebar {
return SidebarFromJSONTyped(json, false)
}
export function SidebarFromJSONTyped(json: any, ignoreDiscriminator: boolean): Sidebar {
if (json == null) {
return json
}
return {
id: json['id'],
singular: json['singular'],
plural: json['plural'],
icon: json['icon'] == null ? undefined : json['icon'],
count: json['count']
}
}
export function SidebarToJSON(json: any): Sidebar {
return SidebarToJSONTyped(json, false)
}
export function SidebarToJSONTyped(
value?: Sidebar | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
singular: value['singular'],
plural: value['plural'],
icon: value['icon'],
count: value['count']
}
}

View File

@@ -0,0 +1,72 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface Table
*/
export interface Table {
/**
*
* @type {string}
* @memberof Table
*/
id: string
/**
*
* @type {string}
* @memberof Table
*/
name: string
}
/**
* Check if a given object implements the Table interface.
*/
export function instanceOfTable(value: object): value is Table {
if (!('id' in value) || value['id'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
return true
}
export function TableFromJSON(json: any): Table {
return TableFromJSONTyped(json, false)
}
export function TableFromJSONTyped(json: any, ignoreDiscriminator: boolean): Table {
if (json == null) {
return json
}
return {
id: json['id'],
name: json['name']
}
}
export function TableToJSON(json: any): Table {
return TableToJSONTyped(json, false)
}
export function TableToJSONTyped(value?: Table | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value
}
return {
id: value['id'],
name: value['name']
}
}

View File

@@ -0,0 +1,116 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface Task
*/
export interface Task {
/**
*
* @type {string}
* @memberof Task
*/
id: string
/**
*
* @type {string}
* @memberof Task
*/
ticket: string
/**
*
* @type {string}
* @memberof Task
*/
name: string
/**
*
* @type {boolean}
* @memberof Task
*/
open: boolean
/**
*
* @type {string}
* @memberof Task
*/
owner?: string
/**
*
* @type {Date}
* @memberof Task
*/
created: Date
/**
*
* @type {Date}
* @memberof Task
*/
updated: Date
}
/**
* Check if a given object implements the Task interface.
*/
export function instanceOfTask(value: object): value is Task {
if (!('id' in value) || value['id'] === undefined) return false
if (!('ticket' in value) || value['ticket'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('open' in value) || value['open'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function TaskFromJSON(json: any): Task {
return TaskFromJSONTyped(json, false)
}
export function TaskFromJSONTyped(json: any, ignoreDiscriminator: boolean): Task {
if (json == null) {
return json
}
return {
id: json['id'],
ticket: json['ticket'],
name: json['name'],
open: json['open'],
owner: json['owner'] == null ? undefined : json['owner'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function TaskToJSON(json: any): Task {
return TaskToJSONTyped(json, false)
}
export function TaskToJSONTyped(value?: Task | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value
}
return {
id: value['id'],
ticket: value['ticket'],
name: value['name'],
open: value['open'],
owner: value['owner'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,81 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface TaskUpdate
*/
export interface TaskUpdate {
/**
*
* @type {string}
* @memberof TaskUpdate
*/
name?: string
/**
*
* @type {boolean}
* @memberof TaskUpdate
*/
open?: boolean
/**
*
* @type {string}
* @memberof TaskUpdate
*/
owner?: string
}
/**
* Check if a given object implements the TaskUpdate interface.
*/
export function instanceOfTaskUpdate(value: object): value is TaskUpdate {
return true
}
export function TaskUpdateFromJSON(json: any): TaskUpdate {
return TaskUpdateFromJSONTyped(json, false)
}
export function TaskUpdateFromJSONTyped(json: any, ignoreDiscriminator: boolean): TaskUpdate {
if (json == null) {
return json
}
return {
name: json['name'] == null ? undefined : json['name'],
open: json['open'] == null ? undefined : json['open'],
owner: json['owner'] == null ? undefined : json['owner']
}
}
export function TaskUpdateToJSON(json: any): TaskUpdate {
return TaskUpdateToJSONTyped(json, false)
}
export function TaskUpdateToJSONTyped(
value?: TaskUpdate | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
name: value['name'],
open: value['open'],
owner: value['owner']
}
}

View File

@@ -0,0 +1,154 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface Ticket
*/
export interface Ticket {
/**
*
* @type {string}
* @memberof Ticket
*/
id: string
/**
*
* @type {string}
* @memberof Ticket
*/
type: string
/**
*
* @type {string}
* @memberof Ticket
*/
name: string
/**
*
* @type {string}
* @memberof Ticket
*/
description: string
/**
*
* @type {boolean}
* @memberof Ticket
*/
open: boolean
/**
*
* @type {string}
* @memberof Ticket
*/
owner?: string
/**
*
* @type {string}
* @memberof Ticket
*/
resolution?: string
/**
*
* @type {object}
* @memberof Ticket
*/
schema: object
/**
*
* @type {object}
* @memberof Ticket
*/
state: object
/**
*
* @type {Date}
* @memberof Ticket
*/
created: Date
/**
*
* @type {Date}
* @memberof Ticket
*/
updated: Date
}
/**
* Check if a given object implements the Ticket interface.
*/
export function instanceOfTicket(value: object): value is Ticket {
if (!('id' in value) || value['id'] === undefined) return false
if (!('type' in value) || value['type'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('description' in value) || value['description'] === undefined) return false
if (!('open' in value) || value['open'] === undefined) return false
if (!('schema' in value) || value['schema'] === undefined) return false
if (!('state' in value) || value['state'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function TicketFromJSON(json: any): Ticket {
return TicketFromJSONTyped(json, false)
}
export function TicketFromJSONTyped(json: any, ignoreDiscriminator: boolean): Ticket {
if (json == null) {
return json
}
return {
id: json['id'],
type: json['type'],
name: json['name'],
description: json['description'],
open: json['open'],
owner: json['owner'] == null ? undefined : json['owner'],
resolution: json['resolution'] == null ? undefined : json['resolution'],
schema: json['schema'],
state: json['state'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function TicketToJSON(json: any): Ticket {
return TicketToJSONTyped(json, false)
}
export function TicketToJSONTyped(
value?: Ticket | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
type: value['type'],
name: value['name'],
description: value['description'],
open: value['open'],
owner: value['owner'],
resolution: value['resolution'],
schema: value['schema'],
state: value['state'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,129 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface TicketSearch
*/
export interface TicketSearch {
/**
*
* @type {string}
* @memberof TicketSearch
*/
id: string
/**
*
* @type {string}
* @memberof TicketSearch
*/
name: string
/**
*
* @type {string}
* @memberof TicketSearch
*/
description: string
/**
*
* @type {boolean}
* @memberof TicketSearch
*/
open: boolean
/**
*
* @type {string}
* @memberof TicketSearch
*/
type: string
/**
*
* @type {object}
* @memberof TicketSearch
*/
state: object
/**
*
* @type {string}
* @memberof TicketSearch
*/
ownerName: string
/**
*
* @type {Date}
* @memberof TicketSearch
*/
created: Date
}
/**
* Check if a given object implements the TicketSearch interface.
*/
export function instanceOfTicketSearch(value: object): value is TicketSearch {
if (!('id' in value) || value['id'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('description' in value) || value['description'] === undefined) return false
if (!('open' in value) || value['open'] === undefined) return false
if (!('type' in value) || value['type'] === undefined) return false
if (!('state' in value) || value['state'] === undefined) return false
if (!('ownerName' in value) || value['ownerName'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
return true
}
export function TicketSearchFromJSON(json: any): TicketSearch {
return TicketSearchFromJSONTyped(json, false)
}
export function TicketSearchFromJSONTyped(json: any, ignoreDiscriminator: boolean): TicketSearch {
if (json == null) {
return json
}
return {
id: json['id'],
name: json['name'],
description: json['description'],
open: json['open'],
type: json['type'],
state: json['state'],
ownerName: json['owner_name'],
created: new Date(json['created'])
}
}
export function TicketSearchToJSON(json: any): TicketSearch {
return TicketSearchToJSONTyped(json, false)
}
export function TicketSearchToJSONTyped(
value?: TicketSearch | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
name: value['name'],
description: value['description'],
open: value['open'],
type: value['type'],
state: value['state'],
owner_name: value['ownerName'],
created: value['created'].toISOString()
}
}

View File

@@ -0,0 +1,121 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface TicketUpdate
*/
export interface TicketUpdate {
/**
*
* @type {string}
* @memberof TicketUpdate
*/
type?: string
/**
*
* @type {string}
* @memberof TicketUpdate
*/
name?: string
/**
*
* @type {string}
* @memberof TicketUpdate
*/
description?: string
/**
*
* @type {boolean}
* @memberof TicketUpdate
*/
open?: boolean
/**
*
* @type {string}
* @memberof TicketUpdate
*/
owner?: string
/**
*
* @type {string}
* @memberof TicketUpdate
*/
resolution?: string
/**
*
* @type {object}
* @memberof TicketUpdate
*/
schema?: object
/**
*
* @type {object}
* @memberof TicketUpdate
*/
state?: object
}
/**
* Check if a given object implements the TicketUpdate interface.
*/
export function instanceOfTicketUpdate(value: object): value is TicketUpdate {
return true
}
export function TicketUpdateFromJSON(json: any): TicketUpdate {
return TicketUpdateFromJSONTyped(json, false)
}
export function TicketUpdateFromJSONTyped(json: any, ignoreDiscriminator: boolean): TicketUpdate {
if (json == null) {
return json
}
return {
type: json['type'] == null ? undefined : json['type'],
name: json['name'] == null ? undefined : json['name'],
description: json['description'] == null ? undefined : json['description'],
open: json['open'] == null ? undefined : json['open'],
owner: json['owner'] == null ? undefined : json['owner'],
resolution: json['resolution'] == null ? undefined : json['resolution'],
schema: json['schema'] == null ? undefined : json['schema'],
state: json['state'] == null ? undefined : json['state']
}
}
export function TicketUpdateToJSON(json: any): TicketUpdate {
return TicketUpdateToJSONTyped(json, false)
}
export function TicketUpdateToJSONTyped(
value?: TicketUpdate | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
type: value['type'],
name: value['name'],
description: value['description'],
open: value['open'],
owner: value['owner'],
resolution: value['resolution'],
schema: value['schema'],
state: value['state']
}
}

View File

@@ -0,0 +1,111 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface TimelineEntry
*/
export interface TimelineEntry {
/**
*
* @type {string}
* @memberof TimelineEntry
*/
id: string
/**
*
* @type {string}
* @memberof TimelineEntry
*/
ticket: string
/**
*
* @type {string}
* @memberof TimelineEntry
*/
message: string
/**
*
* @type {Date}
* @memberof TimelineEntry
*/
time: Date
/**
*
* @type {Date}
* @memberof TimelineEntry
*/
created: Date
/**
*
* @type {Date}
* @memberof TimelineEntry
*/
updated: Date
}
/**
* Check if a given object implements the TimelineEntry interface.
*/
export function instanceOfTimelineEntry(value: object): value is TimelineEntry {
if (!('id' in value) || value['id'] === undefined) return false
if (!('ticket' in value) || value['ticket'] === undefined) return false
if (!('message' in value) || value['message'] === undefined) return false
if (!('time' in value) || value['time'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function TimelineEntryFromJSON(json: any): TimelineEntry {
return TimelineEntryFromJSONTyped(json, false)
}
export function TimelineEntryFromJSONTyped(json: any, ignoreDiscriminator: boolean): TimelineEntry {
if (json == null) {
return json
}
return {
id: json['id'],
ticket: json['ticket'],
message: json['message'],
time: new Date(json['time']),
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function TimelineEntryToJSON(json: any): TimelineEntry {
return TimelineEntryToJSONTyped(json, false)
}
export function TimelineEntryToJSONTyped(
value?: TimelineEntry | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
ticket: value['ticket'],
message: value['message'],
time: value['time'].toISOString(),
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,76 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface TimelineEntryUpdate
*/
export interface TimelineEntryUpdate {
/**
*
* @type {string}
* @memberof TimelineEntryUpdate
*/
message?: string
/**
*
* @type {Date}
* @memberof TimelineEntryUpdate
*/
time?: Date
}
/**
* Check if a given object implements the TimelineEntryUpdate interface.
*/
export function instanceOfTimelineEntryUpdate(value: object): value is TimelineEntryUpdate {
return true
}
export function TimelineEntryUpdateFromJSON(json: any): TimelineEntryUpdate {
return TimelineEntryUpdateFromJSONTyped(json, false)
}
export function TimelineEntryUpdateFromJSONTyped(
json: any,
ignoreDiscriminator: boolean
): TimelineEntryUpdate {
if (json == null) {
return json
}
return {
message: json['message'] == null ? undefined : json['message'],
time: json['time'] == null ? undefined : new Date(json['time'])
}
}
export function TimelineEntryUpdateToJSON(json: any): TimelineEntryUpdate {
return TimelineEntryUpdateToJSONTyped(json, false)
}
export function TimelineEntryUpdateToJSONTyped(
value?: TimelineEntryUpdate | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
message: value['message'],
time: value['time'] == null ? undefined : value['time'].toISOString()
}
}

View File

@@ -0,0 +1,116 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface Type
*/
export interface Type {
/**
*
* @type {string}
* @memberof Type
*/
id: string
/**
*
* @type {string}
* @memberof Type
*/
icon?: string
/**
*
* @type {string}
* @memberof Type
*/
plural: string
/**
*
* @type {object}
* @memberof Type
*/
schema: object
/**
*
* @type {string}
* @memberof Type
*/
singular: string
/**
*
* @type {Date}
* @memberof Type
*/
created: Date
/**
*
* @type {Date}
* @memberof Type
*/
updated: Date
}
/**
* Check if a given object implements the Type interface.
*/
export function instanceOfType(value: object): value is Type {
if (!('id' in value) || value['id'] === undefined) return false
if (!('plural' in value) || value['plural'] === undefined) return false
if (!('schema' in value) || value['schema'] === undefined) return false
if (!('singular' in value) || value['singular'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function TypeFromJSON(json: any): Type {
return TypeFromJSONTyped(json, false)
}
export function TypeFromJSONTyped(json: any, ignoreDiscriminator: boolean): Type {
if (json == null) {
return json
}
return {
id: json['id'],
icon: json['icon'] == null ? undefined : json['icon'],
plural: json['plural'],
schema: json['schema'],
singular: json['singular'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function TypeToJSON(json: any): Type {
return TypeToJSONTyped(json, false)
}
export function TypeToJSONTyped(value?: Type | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value
}
return {
id: value['id'],
icon: value['icon'],
plural: value['plural'],
schema: value['schema'],
singular: value['singular'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,89 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface TypeUpdate
*/
export interface TypeUpdate {
/**
*
* @type {string}
* @memberof TypeUpdate
*/
icon?: string
/**
*
* @type {string}
* @memberof TypeUpdate
*/
plural?: string
/**
*
* @type {object}
* @memberof TypeUpdate
*/
schema?: object
/**
*
* @type {string}
* @memberof TypeUpdate
*/
singular?: string
}
/**
* Check if a given object implements the TypeUpdate interface.
*/
export function instanceOfTypeUpdate(value: object): value is TypeUpdate {
return true
}
export function TypeUpdateFromJSON(json: any): TypeUpdate {
return TypeUpdateFromJSONTyped(json, false)
}
export function TypeUpdateFromJSONTyped(json: any, ignoreDiscriminator: boolean): TypeUpdate {
if (json == null) {
return json
}
return {
icon: json['icon'] == null ? undefined : json['icon'],
plural: json['plural'] == null ? undefined : json['plural'],
schema: json['schema'] == null ? undefined : json['schema'],
singular: json['singular'] == null ? undefined : json['singular']
}
}
export function TypeUpdateToJSON(json: any): TypeUpdate {
return TypeUpdateToJSONTyped(json, false)
}
export function TypeUpdateToJSONTyped(
value?: TypeUpdate | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
icon: value['icon'],
plural: value['plural'],
schema: value['schema'],
singular: value['singular']
}
}

View File

@@ -0,0 +1,145 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface User
*/
export interface User {
/**
*
* @type {string}
* @memberof User
*/
id: string
/**
*
* @type {string}
* @memberof User
*/
username: string
/**
*
* @type {string}
* @memberof User
*/
avatar?: string
/**
*
* @type {string}
* @memberof User
*/
email?: string
/**
*
* @type {Date}
* @memberof User
*/
lastResetSentAt?: Date
/**
*
* @type {Date}
* @memberof User
*/
lastVerificationSentAt?: Date
/**
*
* @type {string}
* @memberof User
*/
name?: string
/**
*
* @type {boolean}
* @memberof User
*/
active: boolean
/**
*
* @type {Date}
* @memberof User
*/
created: Date
/**
*
* @type {Date}
* @memberof User
*/
updated: Date
}
/**
* Check if a given object implements the User interface.
*/
export function instanceOfUser(value: object): value is User {
if (!('id' in value) || value['id'] === undefined) return false
if (!('username' in value) || value['username'] === undefined) return false
if (!('active' in value) || value['active'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function UserFromJSON(json: any): User {
return UserFromJSONTyped(json, false)
}
export function UserFromJSONTyped(json: any, ignoreDiscriminator: boolean): User {
if (json == null) {
return json
}
return {
id: json['id'],
username: json['username'],
avatar: json['avatar'] == null ? undefined : json['avatar'],
email: json['email'] == null ? undefined : json['email'],
lastResetSentAt:
json['lastResetSentAt'] == null ? undefined : new Date(json['lastResetSentAt']),
lastVerificationSentAt:
json['lastVerificationSentAt'] == null ? undefined : new Date(json['lastVerificationSentAt']),
name: json['name'] == null ? undefined : json['name'],
active: json['active'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function UserToJSON(json: any): User {
return UserToJSONTyped(json, false)
}
export function UserToJSONTyped(value?: User | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value
}
return {
id: value['id'],
username: value['username'],
avatar: value['avatar'],
email: value['email'],
lastResetSentAt:
value['lastResetSentAt'] == null ? undefined : value['lastResetSentAt'].toISOString(),
lastVerificationSentAt:
value['lastVerificationSentAt'] == null
? undefined
: value['lastVerificationSentAt'].toISOString(),
name: value['name'],
active: value['active'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,111 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface UserGroup
*/
export interface UserGroup {
/**
*
* @type {string}
* @memberof UserGroup
*/
id: string
/**
*
* @type {string}
* @memberof UserGroup
*/
name: string
/**
*
* @type {Array<string>}
* @memberof UserGroup
*/
permissions: Array<string>
/**
*
* @type {string}
* @memberof UserGroup
*/
type: string
/**
*
* @type {Date}
* @memberof UserGroup
*/
created: Date
/**
*
* @type {Date}
* @memberof UserGroup
*/
updated: Date
}
/**
* Check if a given object implements the UserGroup interface.
*/
export function instanceOfUserGroup(value: object): value is UserGroup {
if (!('id' in value) || value['id'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('permissions' in value) || value['permissions'] === undefined) return false
if (!('type' in value) || value['type'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function UserGroupFromJSON(json: any): UserGroup {
return UserGroupFromJSONTyped(json, false)
}
export function UserGroupFromJSONTyped(json: any, ignoreDiscriminator: boolean): UserGroup {
if (json == null) {
return json
}
return {
id: json['id'],
name: json['name'],
permissions: json['permissions'],
type: json['type'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function UserGroupToJSON(json: any): UserGroup {
return UserGroupToJSONTyped(json, false)
}
export function UserGroupToJSONTyped(
value?: UserGroup | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
name: value['name'],
permissions: value['permissions'],
type: value['type'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,113 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface UserUpdate
*/
export interface UserUpdate {
/**
*
* @type {string}
* @memberof UserUpdate
*/
username?: string
/**
*
* @type {string}
* @memberof UserUpdate
*/
avatar?: string
/**
*
* @type {string}
* @memberof UserUpdate
*/
email?: string
/**
*
* @type {string}
* @memberof UserUpdate
*/
name?: string
/**
*
* @type {string}
* @memberof UserUpdate
*/
password?: string
/**
*
* @type {string}
* @memberof UserUpdate
*/
passwordConfirm?: string
/**
*
* @type {boolean}
* @memberof UserUpdate
*/
active?: boolean
}
/**
* Check if a given object implements the UserUpdate interface.
*/
export function instanceOfUserUpdate(value: object): value is UserUpdate {
return true
}
export function UserUpdateFromJSON(json: any): UserUpdate {
return UserUpdateFromJSONTyped(json, false)
}
export function UserUpdateFromJSONTyped(json: any, ignoreDiscriminator: boolean): UserUpdate {
if (json == null) {
return json
}
return {
username: json['username'] == null ? undefined : json['username'],
avatar: json['avatar'] == null ? undefined : json['avatar'],
email: json['email'] == null ? undefined : json['email'],
name: json['name'] == null ? undefined : json['name'],
password: json['password'] == null ? undefined : json['password'],
passwordConfirm: json['passwordConfirm'] == null ? undefined : json['passwordConfirm'],
active: json['active'] == null ? undefined : json['active']
}
}
export function UserUpdateToJSON(json: any): UserUpdate {
return UserUpdateToJSONTyped(json, false)
}
export function UserUpdateToJSONTyped(
value?: UserUpdate | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
username: value['username'],
avatar: value['avatar'],
email: value['email'],
name: value['name'],
password: value['password'],
passwordConfirm: value['passwordConfirm'],
active: value['active']
}
}

View File

@@ -0,0 +1,111 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface Webhook
*/
export interface Webhook {
/**
*
* @type {string}
* @memberof Webhook
*/
id: string
/**
*
* @type {string}
* @memberof Webhook
*/
name: string
/**
*
* @type {string}
* @memberof Webhook
*/
collection: string
/**
*
* @type {string}
* @memberof Webhook
*/
destination: string
/**
*
* @type {Date}
* @memberof Webhook
*/
created: Date
/**
*
* @type {Date}
* @memberof Webhook
*/
updated: Date
}
/**
* Check if a given object implements the Webhook interface.
*/
export function instanceOfWebhook(value: object): value is Webhook {
if (!('id' in value) || value['id'] === undefined) return false
if (!('name' in value) || value['name'] === undefined) return false
if (!('collection' in value) || value['collection'] === undefined) return false
if (!('destination' in value) || value['destination'] === undefined) return false
if (!('created' in value) || value['created'] === undefined) return false
if (!('updated' in value) || value['updated'] === undefined) return false
return true
}
export function WebhookFromJSON(json: any): Webhook {
return WebhookFromJSONTyped(json, false)
}
export function WebhookFromJSONTyped(json: any, ignoreDiscriminator: boolean): Webhook {
if (json == null) {
return json
}
return {
id: json['id'],
name: json['name'],
collection: json['collection'],
destination: json['destination'],
created: new Date(json['created']),
updated: new Date(json['updated'])
}
}
export function WebhookToJSON(json: any): Webhook {
return WebhookToJSONTyped(json, false)
}
export function WebhookToJSONTyped(
value?: Webhook | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
id: value['id'],
name: value['name'],
collection: value['collection'],
destination: value['destination'],
created: value['created'].toISOString(),
updated: value['updated'].toISOString()
}
}

View File

@@ -0,0 +1,81 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime'
/**
*
* @export
* @interface WebhookUpdate
*/
export interface WebhookUpdate {
/**
*
* @type {string}
* @memberof WebhookUpdate
*/
name?: string
/**
*
* @type {string}
* @memberof WebhookUpdate
*/
collection?: string
/**
*
* @type {string}
* @memberof WebhookUpdate
*/
destination?: string
}
/**
* Check if a given object implements the WebhookUpdate interface.
*/
export function instanceOfWebhookUpdate(value: object): value is WebhookUpdate {
return true
}
export function WebhookUpdateFromJSON(json: any): WebhookUpdate {
return WebhookUpdateFromJSONTyped(json, false)
}
export function WebhookUpdateFromJSONTyped(json: any, ignoreDiscriminator: boolean): WebhookUpdate {
if (json == null) {
return json
}
return {
name: json['name'] == null ? undefined : json['name'],
collection: json['collection'] == null ? undefined : json['collection'],
destination: json['destination'] == null ? undefined : json['destination']
}
}
export function WebhookUpdateToJSON(json: any): WebhookUpdate {
return WebhookUpdateToJSONTyped(json, false)
}
export function WebhookUpdateToJSONTyped(
value?: WebhookUpdate | null,
ignoreDiscriminator: boolean = false
): any {
if (value == null) {
return value
}
return {
name: value['name'],
collection: value['collection'],
destination: value['destination']
}
}

View File

@@ -0,0 +1,53 @@
/* tslint:disable */
/* eslint-disable */
export * from './Comment'
export * from './CommentUpdate'
export * from './Config'
export * from './DashboardCounts'
export * from './EmailTemplate'
export * from './ExtendedComment'
export * from './ExtendedTask'
export * from './ExtendedTicket'
export * from './Feature'
export * from './FileUpdate'
export * from './Group'
export * from './GroupRelation'
export * from './GroupUpdate'
export * from './GroupUser'
export * from './Link'
export * from './LinkUpdate'
export * from './ModelError'
export * from './ModelFile'
export * from './NewComment'
export * from './NewFeature'
export * from './NewFile'
export * from './NewGroup'
export * from './NewLink'
export * from './NewReaction'
export * from './NewTask'
export * from './NewTicket'
export * from './NewTimelineEntry'
export * from './NewType'
export * from './NewUser'
export * from './NewWebhook'
export * from './Reaction'
export * from './ReactionUpdate'
export * from './Settings'
export * from './SettingsMeta'
export * from './SettingsSmtp'
export * from './Sidebar'
export * from './Table'
export * from './Task'
export * from './TaskUpdate'
export * from './Ticket'
export * from './TicketSearch'
export * from './TicketUpdate'
export * from './TimelineEntry'
export * from './TimelineEntryUpdate'
export * from './Type'
export * from './TypeUpdate'
export * from './User'
export * from './UserGroup'
export * from './UserUpdate'
export * from './Webhook'
export * from './WebhookUpdate'

490
ui/src/client/runtime.ts Normal file
View File

@@ -0,0 +1,490 @@
/* tslint:disable */
/* eslint-disable */
/**
* Ticketing System API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
export const BASE_PATH = 'http://localhost:8081'.replace(/\/+$/, '')
export interface ConfigurationParameters {
basePath?: string // override base path
fetchApi?: FetchAPI // override for fetch implementation
middleware?: Middleware[] // middleware to apply before/after fetch requests
queryParamsStringify?: (params: HTTPQuery) => string // stringify function for query strings
username?: string // parameter for basic security
password?: string // parameter for basic security
apiKey?: string | Promise<string> | ((name: string) => string | Promise<string>) // parameter for apiKey security
accessToken?:
| string
| Promise<string>
| ((name?: string, scopes?: string[]) => string | Promise<string>) // parameter for oauth2 security
headers?: HTTPHeaders //header params we want to use on every request
credentials?: RequestCredentials //value for the credentials param we want to use on each request
}
export class Configuration {
constructor(private configuration: ConfigurationParameters = {}) {}
set config(configuration: Configuration) {
this.configuration = configuration
}
get basePath(): string {
return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH
}
get fetchApi(): FetchAPI | undefined {
return this.configuration.fetchApi
}
get middleware(): Middleware[] {
return this.configuration.middleware || []
}
get queryParamsStringify(): (params: HTTPQuery) => string {
return this.configuration.queryParamsStringify || querystring
}
get username(): string | undefined {
return this.configuration.username
}
get password(): string | undefined {
return this.configuration.password
}
get apiKey(): ((name: string) => string | Promise<string>) | undefined {
const apiKey = this.configuration.apiKey
if (apiKey) {
return typeof apiKey === 'function' ? apiKey : () => apiKey
}
return undefined
}
get accessToken(): ((name?: string, scopes?: string[]) => string | Promise<string>) | undefined {
const accessToken = this.configuration.accessToken
if (accessToken) {
return typeof accessToken === 'function' ? accessToken : async () => accessToken
}
return undefined
}
get headers(): HTTPHeaders | undefined {
return this.configuration.headers
}
get credentials(): RequestCredentials | undefined {
return this.configuration.credentials
}
}
export const DefaultConfig = new Configuration()
/**
* This is the base class for all generated API classes.
*/
export class BaseAPI {
private static readonly jsonRegex = new RegExp(
'^(:?application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(:?;.*)?$',
'i'
)
private middleware: Middleware[]
constructor(protected configuration = DefaultConfig) {
this.middleware = configuration.middleware
}
withMiddleware<T extends BaseAPI>(this: T, ...middlewares: Middleware[]) {
const next = this.clone<T>()
next.middleware = next.middleware.concat(...middlewares)
return next
}
withPreMiddleware<T extends BaseAPI>(this: T, ...preMiddlewares: Array<Middleware['pre']>) {
const middlewares = preMiddlewares.map((pre) => ({ pre }))
return this.withMiddleware<T>(...middlewares)
}
withPostMiddleware<T extends BaseAPI>(this: T, ...postMiddlewares: Array<Middleware['post']>) {
const middlewares = postMiddlewares.map((post) => ({ post }))
return this.withMiddleware<T>(...middlewares)
}
/**
* Check if the given MIME is a JSON MIME.
* JSON MIME examples:
* application/json
* application/json; charset=UTF8
* APPLICATION/JSON
* application/vnd.company+json
* @param mime - MIME (Multipurpose Internet Mail Extensions)
* @return True if the given MIME is JSON, false otherwise.
*/
protected isJsonMime(mime: string | null | undefined): boolean {
if (!mime) {
return false
}
return BaseAPI.jsonRegex.test(mime)
}
protected async request(
context: RequestOpts,
initOverrides?: RequestInit | InitOverrideFunction
): Promise<Response> {
const { url, init } = await this.createFetchParams(context, initOverrides)
const response = await this.fetchApi(url, init)
if (response && response.status >= 200 && response.status < 300) {
return response
}
throw new ResponseError(response, 'Response returned an error code')
}
private async createFetchParams(
context: RequestOpts,
initOverrides?: RequestInit | InitOverrideFunction
) {
let url = this.configuration.basePath + context.path
if (context.query !== undefined && Object.keys(context.query).length !== 0) {
// only add the querystring to the URL if there are query parameters.
// this is done to avoid urls ending with a "?" character which buggy webservers
// do not handle correctly sometimes.
url += '?' + this.configuration.queryParamsStringify(context.query)
}
const headers = Object.assign({}, this.configuration.headers, context.headers)
Object.keys(headers).forEach((key) => (headers[key] === undefined ? delete headers[key] : {}))
const initOverrideFn =
typeof initOverrides === 'function' ? initOverrides : async () => initOverrides
const initParams = {
method: context.method,
headers,
body: context.body,
credentials: this.configuration.credentials
}
const overriddenInit: RequestInit = {
...initParams,
...(await initOverrideFn({
init: initParams,
context
}))
}
let body: any
if (
isFormData(overriddenInit.body) ||
overriddenInit.body instanceof URLSearchParams ||
isBlob(overriddenInit.body)
) {
body = overriddenInit.body
} else if (this.isJsonMime(headers['Content-Type'])) {
body = JSON.stringify(overriddenInit.body)
} else {
body = overriddenInit.body
}
const init: RequestInit = {
...overriddenInit,
body
}
return { url, init }
}
private fetchApi = async (url: string, init: RequestInit) => {
let fetchParams = { url, init }
for (const middleware of this.middleware) {
if (middleware.pre) {
fetchParams =
(await middleware.pre({
fetch: this.fetchApi,
...fetchParams
})) || fetchParams
}
}
let response: Response | undefined = undefined
try {
response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init)
} catch (e) {
for (const middleware of this.middleware) {
if (middleware.onError) {
response =
(await middleware.onError({
fetch: this.fetchApi,
url: fetchParams.url,
init: fetchParams.init,
error: e,
response: response ? response.clone() : undefined
})) || response
}
}
if (response === undefined) {
if (e instanceof Error) {
throw new FetchError(
e,
'The request failed and the interceptors did not return an alternative response'
)
} else {
throw e
}
}
}
for (const middleware of this.middleware) {
if (middleware.post) {
response =
(await middleware.post({
fetch: this.fetchApi,
url: fetchParams.url,
init: fetchParams.init,
response: response.clone()
})) || response
}
}
return response
}
/**
* Create a shallow clone of `this` by constructing a new instance
* and then shallow cloning data members.
*/
private clone<T extends BaseAPI>(this: T): T {
const constructor = this.constructor as any
const next = new constructor(this.configuration)
next.middleware = this.middleware.slice()
return next
}
}
function isBlob(value: any): value is Blob {
return typeof Blob !== 'undefined' && value instanceof Blob
}
function isFormData(value: any): value is FormData {
return typeof FormData !== 'undefined' && value instanceof FormData
}
export class ResponseError extends Error {
override name: 'ResponseError' = 'ResponseError'
constructor(
public response: Response,
msg?: string
) {
super(msg)
}
}
export class FetchError extends Error {
override name: 'FetchError' = 'FetchError'
constructor(
public cause: Error,
msg?: string
) {
super(msg)
}
}
export class RequiredError extends Error {
override name: 'RequiredError' = 'RequiredError'
constructor(
public field: string,
msg?: string
) {
super(msg)
}
}
export const COLLECTION_FORMATS = {
csv: ',',
ssv: ' ',
tsv: '\t',
pipes: '|'
}
export type FetchAPI = WindowOrWorkerGlobalScope['fetch']
export type Json = any
export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD'
export type HTTPHeaders = { [key: string]: string }
export type HTTPQuery = {
[key: string]:
| string
| number
| null
| boolean
| Array<string | number | null | boolean>
| Set<string | number | null | boolean>
| HTTPQuery
}
export type HTTPBody = Json | FormData | URLSearchParams
export type HTTPRequestInit = {
headers?: HTTPHeaders
method: HTTPMethod
credentials?: RequestCredentials
body?: HTTPBody
}
export type ModelPropertyNaming = 'camelCase' | 'snake_case' | 'PascalCase' | 'original'
export type InitOverrideFunction = (requestContext: {
init: HTTPRequestInit
context: RequestOpts
}) => Promise<RequestInit>
export interface FetchParams {
url: string
init: RequestInit
}
export interface RequestOpts {
path: string
method: HTTPMethod
headers: HTTPHeaders
query?: HTTPQuery
body?: HTTPBody
}
export function querystring(params: HTTPQuery, prefix: string = ''): string {
return Object.keys(params)
.map((key) => querystringSingleKey(key, params[key], prefix))
.filter((part) => part.length > 0)
.join('&')
}
function querystringSingleKey(
key: string,
value:
| string
| number
| null
| undefined
| boolean
| Array<string | number | null | boolean>
| Set<string | number | null | boolean>
| HTTPQuery,
keyPrefix: string = ''
): string {
const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key)
if (value instanceof Array) {
const multiValue = value
.map((singleValue) => encodeURIComponent(String(singleValue)))
.join(`&${encodeURIComponent(fullKey)}=`)
return `${encodeURIComponent(fullKey)}=${multiValue}`
}
if (value instanceof Set) {
const valueAsArray = Array.from(value)
return querystringSingleKey(key, valueAsArray, keyPrefix)
}
if (value instanceof Date) {
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`
}
if (value instanceof Object) {
return querystring(value as HTTPQuery, fullKey)
}
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`
}
export function exists(json: any, key: string) {
const value = json[key]
return value !== null && value !== undefined
}
export function mapValues(data: any, fn: (item: any) => any) {
const result: { [key: string]: any } = {}
for (const key of Object.keys(data)) {
result[key] = fn(data[key])
}
return result
}
export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if ('multipart/form-data' === consume.contentType) {
return true
}
}
return false
}
export interface Consume {
contentType: string
}
export interface RequestContext {
fetch: FetchAPI
url: string
init: RequestInit
}
export interface ResponseContext {
fetch: FetchAPI
url: string
init: RequestInit
response: Response
}
export interface ErrorContext {
fetch: FetchAPI
url: string
init: RequestInit
error: unknown
response?: Response
}
export interface Middleware {
pre?(context: RequestContext): Promise<FetchParams | void>
post?(context: ResponseContext): Promise<Response | void>
onError?(context: ErrorContext): Promise<Response | void>
}
export interface ApiResponse<T> {
raw: Response
value(): Promise<T>
}
export interface ResponseTransformer<T> {
(json: any): T
}
export class JSONApiResponse<T> {
constructor(
public raw: Response,
private transformer: ResponseTransformer<T> = (jsonValue: any) => jsonValue
) {}
async value(): Promise<T> {
return this.transformer(await this.raw.json())
}
}
export class VoidApiResponse {
constructor(public raw: Response) {}
async value(): Promise<void> {
return undefined
}
}
export class BlobApiResponse {
constructor(public raw: Response) {}
async value(): Promise<Blob> {
return await this.raw.blob()
}
}
export class TextApiResponse {
constructor(public raw: Response) {}
async value(): Promise<string> {
return await this.raw.text()
}
}

View File

@@ -4,31 +4,32 @@ import * as icons from 'lucide-vue-next'
import { computed } from 'vue'
const props = defineProps({
name: {
type: String,
required: true
},
name: String,
size: Number,
color: String,
strokeWidth: Number,
defaultClass: String
})
const icon = computed((): string => {
if (!icons[props.name]) {
return 'Flame'
const IconComponent = computed(() => {
if (!props.name) {
return icons.HelpCircle
}
return icons[props.name]
const component = icons[props.name]
if (!component) {
return icons.HelpCircle
}
return component
})
</script>
<template>
<component
:is="icon"
:is="IconComponent"
:size="size"
:color="color"
:stroke-width="strokeWidth"
:default-class="defaultClass"
:class="defaultClass"
/>
</template>

View File

@@ -1,16 +1,16 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: string
defineProps<{
size: number
}>()
</script>
<template>
<img src="@/assets/flask.svg" alt="Catalyst Logo" :class="cn('dark:hidden', props.class)" />
<img src="@/assets/flask.svg" alt="Catalyst Logo" :class="cn('dark:hidden', 'size-' + size)" />
<img
src="@/assets/flask_white.svg"
alt="Catalyst Logo"
:class="cn('hidden dark:flex', props.class)"
:class="cn('hidden dark:flex', 'size-' + size)"
/>
</template>

View File

@@ -13,42 +13,29 @@ import {
import { Trash2 } from 'lucide-vue-next'
import { useMutation, useQueryClient } from '@tanstack/vue-query'
import { ref } from 'vue'
import { type RouteLocationRaw, useRouter } from 'vue-router'
import { pb } from '@/lib/pocketbase'
import { handleError } from '@/lib/utils'
const queryClient = useQueryClient()
const router = useRouter()
const props = defineProps<{
collection: string
id: string
name: string
singular: string
queryKey: string[]
to?: RouteLocationRaw
}>()
const isOpen = ref(false)
const deleteMutation = useMutation({
mutationFn: () => pb.collection(props.collection).delete(props.id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: props.queryKey })
if (props.to) router.push(props.to)
},
onError: handleError
})
const emit = defineEmits<{
(e: 'delete'): void
}>()
const deleteRecord = () => {
emit('delete')
}
</script>
<template>
<Dialog v-model:open="isOpen">
<DialogTrigger as-child>
<slot>
<Button variant="outline">
<Button role="button" variant="outline">
<Trash2 class="mr-2 h-4 w-4" />
Delete {{ props.singular }}
</Button>
@@ -64,7 +51,7 @@ const deleteMutation = useMutation({
</DialogHeader>
<DialogFooter class="mt-2 sm:justify-start">
<Button type="button" variant="destructive" @click="deleteMutation.mutate"> Delete </Button>
<Button type="button" variant="destructive" @click="deleteRecord"> Delete </Button>
<DialogClose as-child>
<Button type="button" variant="secondary">Cancel</Button>
</DialogClose>

View File

@@ -1,23 +1,36 @@
<script setup lang="ts">
import UserSelectList from '@/components/common/UserSelectList.vue'
import { Button } from '@/components/ui/button'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { ref } from 'vue'
import { User2 } from 'lucide-vue-next'
import type { User } from '@/lib/types'
import type { User } from '@/client'
const user = defineModel<User>()
defineProps<{
userID?: string
userName?: string
}>()
const open = ref(false)
const select = (user: User) => {
emit('select', user)
}
const emit = defineEmits<{
(e: 'select', value: User): void
}>()
</script>
<template>
<Popover v-model:open="open">
<Popover>
<PopoverTrigger as-child>
<slot />
<Button variant="outline" role="combobox">
<User2 class="mr-2 size-4 h-4 w-4 shrink-0 opacity-50" />
{{ userName ? userName : 'Unassigned' }}
</Button>
</PopoverTrigger>
<PopoverContent class="w-[150px] p-0">
<UserSelectList v-model="user" :key="user ? user.id : 'unassigned'" :user="user" />
<UserSelectList :userID="userID" @select="select" />
</PopoverContent>
</Popover>
</template>

View File

@@ -14,13 +14,16 @@ import { useQuery } from '@tanstack/vue-query'
import debounce from 'lodash.debounce'
import { ref, watch } from 'vue'
import { pb } from '@/lib/pocketbase'
import type { User } from '@/lib/types'
import { useAPI } from '@/api'
import type { User } from '@/client'
import { cn } from '@/lib/utils'
const user = defineModel<User>()
const api = useAPI()
defineProps<{
userID: string | undefined
}>()
const open = ref(false)
const searchTerm = ref('')
const {
@@ -32,11 +35,16 @@ const {
} = useQuery({
queryKey: ['users', 'search', searchTerm.value],
queryFn: () =>
pb.collection('users').getFullList({
sort: 'name',
perPage: 5,
filter: pb.filter(`name ~ {:search}`, { search: searchTerm.value })
})
api
.listUsers()
.then((users) =>
users.filter(
(user) =>
user.name.toLowerCase().includes(searchTerm.value.toLowerCase()) ||
user.username.toLowerCase().includes(searchTerm.value.toLowerCase()) ||
user.email.toLowerCase().includes(searchTerm.value.toLowerCase())
)
)
})
const searchUserDebounced = debounce(() => refetch(), 300)
@@ -45,10 +53,14 @@ watch(
() => searchTerm.value,
() => searchUserDebounced()
)
const emit = defineEmits<{
(e: 'select', value: User): void
}>()
</script>
<template>
<Command v-model="user" v-model:search-term="searchTerm">
<Command v-model:search-term="searchTerm">
<CommandInput placeholder="Search user..." />
<CommandEmpty>
<span v-if="usersIsPending"> Loading... </span>
@@ -61,11 +73,11 @@ watch(
v-for="u in users"
:key="u.id"
:value="u"
@select="open = false"
@select="emit('select', u)"
class="cursor-pointer"
>
<Check
:class="cn('mr-2 h-4 w-4', user && user.id === u.id ? 'opacity-100' : 'opacity-0')"
:class="cn('mr-2 h-4 w-4', userID && userID === u.id ? 'opacity-100' : 'opacity-0')"
/>
{{ u.name }}
</CommandItem>

View File

@@ -8,9 +8,14 @@ import { ChevronRight } from 'lucide-vue-next'
import { useQuery } from '@tanstack/vue-query'
import { pb } from '@/lib/pocketbase'
import type { Task } from '@/lib/types'
import { useAPI } from '@/api'
import type { ExtendedTask } from '@/client/models'
import { cn } from '@/lib/utils'
import { useAuthStore } from '@/store/auth'
const api = useAPI()
const authStore = useAuthStore()
const {
isPending,
@@ -19,13 +24,10 @@ const {
error
} = useQuery({
queryKey: ['tasks'],
queryFn: (): Promise<Array<Task>> => {
if (!pb.authStore.model) return Promise.reject('Not authenticated')
return pb.collection('tasks').getFullList({
sort: '-created',
filter: pb.filter(`open = true && owner = {:owner}`, { owner: pb.authStore.model.id }),
expand: 'owner,ticket'
})
queryFn: (): Promise<Array<ExtendedTask>> => {
return api
.listTasks()
.then((tasks) => tasks.filter((task) => task.open && task.owner === authStore.user?.id))
}
})
</script>
@@ -42,17 +44,17 @@ const {
<RouterLink
:to="{
name: 'tickets',
params: { type: task.expand.ticket.type, id: task.expand.ticket.id }
params: { type: task.ticketType, id: task.ticket }
}"
:class="
cn(
buttonVariants({ variant: 'outline', size: 'sm' }),
'h-8 w-full sm:ml-auto sm:w-auto'
'h-8 w-full sm:w-auto md:ml-auto'
)
"
>
<span class="flex flex-row items-center text-sm text-gray-500">
Go to {{ task.expand.ticket.name }}
Open
<ChevronRight class="ml-2 h-4 w-4" />
</span>
</RouterLink>

View File

@@ -9,29 +9,28 @@ import { ChevronRight } from 'lucide-vue-next'
import { useQuery } from '@tanstack/vue-query'
import { intervalToDuration } from 'date-fns'
import { pb } from '@/lib/pocketbase'
import type { Ticket } from '@/lib/types'
import { useAPI } from '@/api'
import type { ExtendedTicket } from '@/client/models'
import { cn } from '@/lib/utils'
import { useAuthStore } from '@/store/auth'
const {
isPending,
isError,
data: tickets,
error
} = useQuery({
const api = useAPI()
const authStore = useAuthStore()
const { data: tickets } = useQuery({
queryKey: ['tickets', 'dashboard'],
queryFn: (): Promise<Array<Ticket>> => {
if (!pb.authStore.model) return Promise.reject('Not authenticated')
return pb.collection('tickets').getFullList({
sort: '-created',
filter: pb.filter(`open = true && owner = {:owner}`, { owner: pb.authStore.model.id }),
expand: 'owner,type'
})
queryFn: (): Promise<Array<ExtendedTicket>> => {
return api
.listTickets()
.then((tickets) =>
tickets.filter((ticket) => ticket.open && ticket.owner === authStore.user?.id)
)
}
})
const age = (ticket: Ticket) => {
const days = intervalToDuration({ start: new Date(ticket.created), end: new Date() }).days
const age = (ticket: ExtendedTicket) => {
const days = intervalToDuration({ start: ticket.created, end: new Date() }).days
if (!days) return 'today'
if (days === 1) return 'yesterday'
@@ -48,9 +47,9 @@ const age = (ticket: Ticket) => {
</div>
<PanelListElement v-else v-for="ticket in tickets" :key="ticket.id" class="gap-2 pr-1">
<span>{{ ticket.name }}</span>
<Separator orientation="vertical" class="hidden h-4 sm:block" />
<span class="text-sm text-muted-foreground">{{ ticket.expand.type.singular }}</span>
<Separator orientation="vertical" class="hidden h-4 sm:block" />
<Separator orientation="vertical" class="hidden h-4 md:block" />
<span class="text-sm text-muted-foreground">{{ ticket.typeSingular }}</span>
<Separator orientation="vertical" class="hidden h-4 md:block" />
<span class="text-sm text-muted-foreground">Open since {{ age(ticket) }}</span>
<RouterLink
:to="{
@@ -60,12 +59,12 @@ const age = (ticket: Ticket) => {
:class="
cn(
buttonVariants({ variant: 'outline', size: 'sm' }),
'h-8 w-full sm:ml-auto sm:w-auto'
'h-8 w-full sm:w-auto md:ml-auto'
)
"
>
<span class="flex flex-row items-center text-sm text-gray-500">
Go to {{ ticket.name }}
Open
<ChevronRight class="ml-2 h-4 w-4" />
</span>
</RouterLink>

View File

@@ -6,8 +6,10 @@ import { useQuery } from '@tanstack/vue-query'
import { getWeek } from 'date-fns'
import { computed } from 'vue'
import { pb } from '@/lib/pocketbase'
import type { Task } from '@/lib/types'
import { useAPI } from '@/api'
import type { Ticket } from '@/client/models'
const api = useAPI()
const {
isPending,
@@ -16,11 +18,7 @@ const {
error
} = useQuery({
queryKey: ['tickets'],
queryFn: (): Promise<Array<Task>> =>
pb.collection('tickets').getFullList({
sort: '-created',
expand: 'owner,type'
})
queryFn: (): Promise<Array<Ticket>> => api.listTickets()
})
const ticketsPerWeek = computed(() => {

View File

@@ -5,7 +5,10 @@ import { DonutChart } from '@/components/ui/chart-donut'
import { useQuery } from '@tanstack/vue-query'
import { computed } from 'vue'
import { pb } from '@/lib/pocketbase'
import { useAPI } from '@/api'
import type { Sidebar } from '@/client/models'
const api = useAPI()
const {
isPending,
@@ -14,7 +17,7 @@ const {
error
} = useQuery({
queryKey: ['sidebar'],
queryFn: (): Promise<Array<any>> => pb.collection('sidebar').getFullList()
queryFn: (): Promise<Array<Sidebar>> => api.getSidebar()
})
const namedTypes = computed(() => {

View File

@@ -0,0 +1,100 @@
<script setup lang="ts">
import Icon from '@/components/Icon.vue'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { computed, ref } from 'vue'
const modelValue = defineModel<string>({
default: ''
})
const isOpen = ref(false)
const searchTerm = ref('')
const iconMap = [
// Priority/Importance
{ name: 'Flame' },
{ name: 'Star' },
{ name: 'Flag' },
{ name: 'Bell' },
{ name: 'BellRing' },
{ name: 'Shield' },
{ name: 'ShieldAlert' },
{ name: 'Siren' },
// Status/State
{ name: 'HelpCircle' },
{ name: 'Info' },
{ name: 'AlertCircle' },
{ name: 'AlertTriangle' },
{ name: 'CheckCircle' },
{ name: 'XCircle' },
{ name: 'Clock' },
{ name: 'Timer' },
// Action/Process
{ name: 'Calendar' },
{ name: 'FileText' },
{ name: 'FileQuestion' },
{ name: 'FileWarning' },
{ name: 'User' },
// Communication
{ name: 'MessageSquare' },
{ name: 'MessageCircle' },
{ name: 'Mail' },
// System/Technical
{ name: 'Settings' },
{ name: 'Wrench' },
{ name: 'Hammer' },
{ name: 'Code' },
{ name: 'Bug' },
{ name: 'Database' },
{ name: 'Server' },
{ name: 'Cloud' }
]
// Get all icon names that are actual components
const iconNames = computed(() =>
iconMap.filter((icon) => {
return icon.name.toLowerCase().includes(searchTerm.value.toLowerCase())
})
)
const selectIcon = (name: string) => {
modelValue.value = name
isOpen.value = false
}
</script>
<template>
<div class="flex items-center gap-2">
<Popover>
<PopoverTrigger>
<Button
type="button"
variant="outline"
role="combobox"
class="flex items-center justify-start gap-2"
>
<Icon :name="modelValue || 'CircleHelp'" class="size-4" />
</Button>
</PopoverTrigger>
<PopoverContent align="start" class="grid w-full grid-cols-8 gap-2 p-2">
<Button
v-for="icon in iconNames"
:key="icon.name"
type="button"
@click="selectIcon(icon.name)"
class="cursor-pointer"
variant="ghost"
>
<Icon :name="icon.name || 'CircleHelp'" class="size-4" />
</Button>
</PopoverContent>
</Popover>
<Input v-model="modelValue" />
</div>
</template>

View File

@@ -14,7 +14,19 @@ import {
import isEqual from 'lodash.isequal'
import { onMounted, ref, watch } from 'vue'
import type { JSONSchema } from '@/lib/types'
interface JSONSchema {
type: 'object'
properties: Record<
string,
{
title: string
type: string
description?: string
enum?: Array<string>
}
>
required?: Array<string>
}
const model = defineModel<Record<string, any>>()
@@ -27,7 +39,7 @@ const formdata = ref<Record<string, any>>({})
onMounted(() => {
if (!model.value) return
for (const key in props.schema.properties) {
for (const key in props.schema?.properties) {
formdata.value[key] = model.value[key]
}
})
@@ -47,7 +59,7 @@ watch(
</script>
<template>
<div v-for="(property, key) in schema.properties" :key="key">
<div v-for="(property, key) in schema?.properties" :key="key">
<FormField v-if="property.enum" :name="key" v-slot="{ componentField }" v-model="formdata[key]">
<FormItem>
<FormLabel :for="key" class="text-right">

View File

@@ -16,11 +16,13 @@ const props = withDefaults(
modelValue?: string[]
items: string[]
placeholder?: string
disabled?: boolean
}>(),
{
modelValue: () => [],
items: () => [],
placeholder: ''
placeholder: '',
disabled: false
}
)
@@ -40,18 +42,26 @@ const filteredItems = computed(() => {
if (!selectedItems.value) return props.items
return props.items.filter((i) => !selectedItems.value.includes(i))
})
const removeItem = (item: string) => {
const index = selectedItems.value.indexOf(item)
if (index > -1) {
selectedItems.value.splice(index, 1)
}
}
</script>
<template>
<TagsInput class="flex items-center gap-2 px-0" :modelValue="selectedItems">
<div class="flex flex-wrap items-center">
<TagsInputItem v-for="item in selectedItems" :key="item" :value="item" class="ml-2">
<TagsInput class="flex items-center gap-2 px-2" :modelValue="selectedItems">
<div class="flex flex-wrap items-center gap-2">
<TagsInputItem v-for="item in selectedItems" :key="item" :value="item">
<TagsInputItemText />
<TagsInputItemDelete />
<TagsInputItemDelete v-if="!disabled" @click="removeItem(item)" />
</TagsInputItem>
</div>
<ComboboxRoot
v-if="!disabled"
v-model="selectedItems"
v-model:open="open"
v-model:searchTerm="searchTerm"
@@ -71,7 +81,7 @@ const filteredItems = computed(() => {
<CommandList
v-if="selectedItems.length < items.length"
position="popper"
class="mt-2 w-[--radix-popper-anchor-width] rounded-md border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
class="w-(--radix-popper-anchor-width) mt-2 rounded-md border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
>
<CommandEmpty />
<CommandGroup>

View File

@@ -0,0 +1,98 @@
<script setup lang="ts">
import TanView from '@/components/TanView.vue'
import DeleteDialog from '@/components/common/DeleteDialog.vue'
import GroupForm from '@/components/group/GroupForm.vue'
import GroupGroup from '@/components/group/GroupGroup.vue'
import ColumnBody from '@/components/layout/ColumnBody.vue'
import ColumnBodyContainer from '@/components/layout/ColumnBodyContainer.vue'
import ColumnHeader from '@/components/layout/ColumnHeader.vue'
import { Button } from '@/components/ui/button'
import { useToast } from '@/components/ui/toast/use-toast'
import { ChevronLeft } from 'lucide-vue-next'
import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query'
import { useRouter } from 'vue-router'
import { useAPI } from '@/api'
import type { Group, GroupUpdate } from '@/client/models'
import { handleError } from '@/lib/utils'
const api = useAPI()
const router = useRouter()
const queryClient = useQueryClient()
const { toast } = useToast()
const props = defineProps<{
id: string
}>()
const {
isPending,
isError,
data: group,
error
} = useQuery({
queryKey: ['groups', props.id],
queryFn: (): Promise<Group> => api.getGroup({ id: props.id })
})
const updateGroupMutation = useMutation({
mutationFn: (update: GroupUpdate) => api.updateGroup({ id: props.id, groupUpdate: update }),
onSuccess: () => {
toast({
title: 'Group updated',
description: 'The group has been updated successfully'
})
queryClient.invalidateQueries({ queryKey: ['groups'] })
},
onError: handleError('Failed to update group')
})
const deleteMutation = useMutation({
mutationFn: () => api.deleteGroup({ id: props.id }),
onSuccess: () => {
queryClient.removeQueries({ queryKey: ['groups', props.id] })
queryClient.invalidateQueries({ queryKey: ['groups'] })
toast({
title: 'Group deleted',
description: 'The group has been deleted successfully'
})
router.push({ name: 'groups' })
},
onError: handleError('Failed to delete group')
})
</script>
<template>
<TanView :isError="isError" :isPending="isPending" :error="error">
<ColumnHeader>
<Button @click="router.push({ name: 'groups' })" variant="outline" class="md:hidden">
<ChevronLeft class="mr-2 size-4" />
Back
</Button>
<div class="ml-auto">
<DeleteDialog
v-if="group && group.id !== 'admin'"
:name="group.name"
singular="Group"
@delete="deleteMutation.mutate"
/>
</div>
</ColumnHeader>
<ColumnBody v-if="group">
<ColumnBodyContainer>
<div class="flex flex-col gap-4 xl:flex-row">
<div class="flex flex-col gap-4 xl:flex-1">
<GroupForm :group="group" @submit="updateGroupMutation.mutate" />
</div>
<div class="flex w-full flex-col gap-4 xl:w-96 xl:shrink-0">
<GroupGroup :id="group.id" />
</div>
</div>
</ColumnBodyContainer>
</ColumnBody>
</TanView>
</template>

View File

@@ -0,0 +1,201 @@
<script setup lang="ts">
import MultiSelect from '@/components/form/MultiSelect.vue'
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { Button } from '@/components/ui/button'
import { FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
import { useQuery } from '@tanstack/vue-query'
import { defineRule, useForm } from 'vee-validate'
import { computed, ref, watch } from 'vue'
import { useAPI } from '@/api'
import type { NewGroup } from '@/client'
const api = useAPI()
const submitDisabledReason = ref<string>('')
const props = defineProps<{
group?: NewGroup
}>()
const emit = defineEmits(['submit'])
const isDemo = ref(false)
const { data: config } = useQuery({
queryKey: ['config'],
queryFn: () => api.getConfig()
})
watch(
() => config.value,
() => {
if (!config.value) return
if (config.value.flags.includes('demo')) {
isDemo.value = true
}
},
{ immediate: true }
)
defineRule('required', (value: string) => {
if (!value || !value.length) {
return 'This field is required'
}
return true
})
const { handleSubmit, validate, values } = useForm({
initialValues: () => ({
name: props.group?.name || '',
permissions: props.group?.permissions || []
}),
validationSchema: {
name: 'required'
}
})
const equalGroup = (values: NewGroup, group?: NewGroup): boolean => {
if (!group) return false
return group.name === values.name && equalElements(group.permissions, values.permissions)
}
const equalElements = (a: string[], b: string[]): boolean => {
if (a.length !== b.length) return false
const sortedA = [...a].sort()
const sortedB = [...b].sort()
return sortedA.every((value, index) => value === sortedB[index])
}
const updateSubmitDisabledReason = () => {
if (props.group && props.group.name === 'Admin') {
submitDisabledReason.value = 'The admin group cannot be edited'
return
}
if (isDemo.value) {
submitDisabledReason.value = 'Groups cannot be created or edited in demo mode'
return
}
if (equalGroup(values, props.group)) {
submitDisabledReason.value = 'Make changes to save'
return
}
validate({ mode: 'silent' }).then((res) => {
if (res.valid) {
submitDisabledReason.value = ''
} else {
submitDisabledReason.value = 'Please fix the errors'
}
})
}
watch(
() => isDemo.value,
() => updateSubmitDisabledReason()
)
watch(
() => props.group,
() => updateSubmitDisabledReason(),
{ immediate: true }
)
watch(
() => values,
() => updateSubmitDisabledReason(),
{ deep: true, immediate: true }
)
const onSubmit = handleSubmit((values) => {
emit('submit', {
name: values.name,
permissions: values.permissions
})
})
const permissionItems = computed(() => config.value?.permissions || [])
</script>
<template>
<form @submit="onSubmit" class="flex w-full flex-col items-start gap-4">
<FormField name="name" v-slot="{ componentField }" validate-on-input>
<FormItem class="w-full">
<FormLabel for="name" class="text-right">Name</FormLabel>
<Input
id="name"
class="col-span-3"
v-bind="componentField"
:disabled="group && group.name === 'Admin'"
/>
<FormMessage />
</FormItem>
</FormField>
<FormField
key="permission.name"
name="permissions"
v-slot="{ componentField }"
validate-on-input
>
<FormItem id="permissions" class="w-full">
<div class="space-y-0.5">
<FormLabel for="permissions" class="text-right">Permissions</FormLabel>
</div>
<FormControl>
<MultiSelect
v-bind="componentField"
:items="permissionItems"
placeholder="Select permissions..."
:disabled="values.name === 'Admin'"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
<Alert v-if="isDemo" variant="destructive">
<AlertTitle>Cannot save</AlertTitle>
<AlertDescription>{{ submitDisabledReason }}</AlertDescription>
</Alert>
<Alert v-if="values.name === 'Admin'">
<AlertTitle>Cannot save</AlertTitle>
<AlertDescription>{{ submitDisabledReason }}</AlertDescription>
</Alert>
<div v-if="values.name !== 'Admin'" class="flex gap-4">
<TooltipProvider :delay-duration="0">
<Tooltip>
<TooltipTrigger class="cursor-default">
<Button
role="submit"
:variant="submitDisabledReason !== '' ? 'secondary' : 'default'"
:disabled="submitDisabledReason !== ''"
:title="submitDisabledReason"
>
Save
</Button>
</TooltipTrigger>
<TooltipContent>
<span v-if="submitDisabledReason !== ''">
{{ submitDisabledReason }}
</span>
<span v-else> Save the group. </span>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<slot name="cancel"></slot>
</div>
</form>
</template>

View File

@@ -0,0 +1,323 @@
<script setup lang="ts">
import DeleteDialog from '@/components/common/DeleteDialog.vue'
import GroupSelectDialog from '@/components/group/GroupSelectDialog.vue'
import PanelListElement from '@/components/layout/PanelListElement.vue'
import TicketPanel from '@/components/ticket/TicketPanel.vue'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { useToast } from '@/components/ui/toast/use-toast'
import UserSelectDialog from '@/components/user/UserSelectDialog.vue'
import { Trash2 } from 'lucide-vue-next'
import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query'
import { ref } from 'vue'
import { useAPI } from '@/api'
import type { GroupUser, UserGroup } from '@/client'
import { handleError } from '@/lib/utils'
const api = useAPI()
const queryClient = useQueryClient()
const { toast } = useToast()
const props = defineProps<{
id: string
}>()
const { data: parentGroups } = useQuery({
queryKey: ['parent_groups', props.id],
queryFn: (): Promise<Array<UserGroup>> => api.listParentGroups({ id: props.id })
})
const { data: parentPermissions } = useQuery({
queryKey: ['parent_permissions', props.id],
queryFn: (): Promise<Array<string>> => api.listParentPermissions({ id: props.id })
})
const { data: childGroups } = useQuery({
queryKey: ['child_groups', props.id],
queryFn: (): Promise<Array<UserGroup>> => api.listChildGroups({ id: props.id })
})
const { data: groupUsers } = useQuery({
queryKey: ['group_users', props.id],
queryFn: (): Promise<Array<GroupUser>> => api.listGroupUsers({ id: props.id })
})
const addGroupUserMutation = useMutation({
mutationFn: (id: string): Promise<void> =>
api.addUserGroup({
id: id,
groupRelation: {
groupId: props.id
}
}),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['group_users'] })
toast({
title: 'User added',
description: 'The user has been added to the group'
})
},
onError: handleError('Failed to add user to group')
})
const addGroupParentMutation = useMutation({
mutationFn: (id: string): Promise<void> =>
api.addGroupParent({
id: id,
groupRelation: {
groupId: props.id
}
}),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['parent_groups'] })
queryClient.invalidateQueries({ queryKey: ['parent_permissions'] })
toast({
title: 'Parent group added',
description: 'The parent group has been added successfully'
})
},
onError: handleError('Failed to add parent group')
})
const addGroupChildMutation = useMutation({
mutationFn: (id: string): Promise<void> =>
api.addGroupParent({
id: props.id,
groupRelation: {
groupId: id
}
}),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['child_groups'] })
toast({
title: 'Child group added',
description: 'The child group has been added successfully'
})
},
onError: handleError('Failed to add child group')
})
const removeGroupUserMutation = useMutation({
mutationFn: (id: string): Promise<void> =>
api.removeUserGroup({
id: id,
groupId: props.id
}),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['group_users'] })
toast({
title: 'User removed',
description: 'The user has been removed from the group'
})
},
onError: handleError('Failed to remove user from group')
})
const removeGroupParentMutation = useMutation({
mutationFn: (id: string): Promise<void> =>
api.removeGroupParent({
id: id,
parentGroupId: props.id
}),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['parent_groups'] })
queryClient.invalidateQueries({ queryKey: ['parent_permissions'] })
toast({
title: 'Parent group removed',
description: 'The parent group has been removed successfully'
})
},
onError: handleError('Failed to remove parent group')
})
const removeGroupChildMutation = useMutation({
mutationFn: (id: string): Promise<void> =>
api.removeGroupParent({
id: props.id,
parentGroupId: id
}),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['child_groups'] })
toast({
title: 'Child group removed',
description: 'The child group has been removed successfully'
})
},
onError: handleError('Failed to remove child group')
})
const dialogOpenParent = ref(false)
const dialogOpenChild = ref(false)
const dialogOpenUser = ref(false)
const selectParent = (group: { group: string }) => {
addGroupParentMutation.mutate(group.group)
dialogOpenParent.value = false
}
const selectChild = (group: { group: string }) => {
addGroupChildMutation.mutate(group.group)
dialogOpenChild.value = false
}
const selectUser = (user: { user: string }) => {
addGroupUserMutation.mutate(user.user)
dialogOpenUser.value = false
}
</script>
<template>
<Card>
<CardHeader>
<CardTitle>Members</CardTitle>
</CardHeader>
<CardContent>
<div class="flex flex-col gap-4">
<TicketPanel title="Child Groups" @add="dialogOpenChild = true">
<GroupSelectDialog
v-model="dialogOpenChild"
@select="selectChild"
:exclude="childGroups?.map((group) => group.id).concat([id]) ?? [id]"
/>
<PanelListElement
v-for="groupGroup in childGroups"
:key="groupGroup.id"
class="flex h-10 flex-row items-center pr-1"
>
<div class="flex flex-1 items-center overflow-hidden">
<RouterLink
:to="{ name: 'groups', params: { id: groupGroup.id } }"
class="hover:underline"
>
{{ groupGroup.name }}
</RouterLink>
<span class="ml-1 text-sm text-muted-foreground">({{ groupGroup.type }})</span>
</div>
<DeleteDialog
v-if="groupGroup.type === 'direct'"
:name="groupGroup.name"
singular="Membership"
@delete="removeGroupChildMutation.mutate(groupGroup.id)"
>
<Button variant="ghost" size="icon" class="h-8 w-8">
<Trash2 class="size-4" />
</Button>
</DeleteDialog>
</PanelListElement>
<div
v-if="!childGroups || childGroups.length === 0"
class="flex h-10 items-center p-4 text-muted-foreground"
>
No groups assigned yet.
</div>
</TicketPanel>
</div>
<div class="mt-4 flex flex-col gap-4">
<TicketPanel title="Users" @add="dialogOpenUser = true">
<UserSelectDialog
v-model="dialogOpenUser"
@select="selectUser"
:exclude="groupUsers?.map((user) => user.id) ?? []"
/>
<PanelListElement
v-for="groupUser in groupUsers"
:key="groupUser.id"
class="flex h-10 flex-row items-center pr-1"
>
<div class="flex flex-1 items-center overflow-hidden">
<RouterLink
:to="{ name: 'users', params: { id: groupUser.id } }"
class="hover:underline"
>
{{ groupUser.name }}
</RouterLink>
<span class="ml-1 text-sm text-muted-foreground">({{ groupUser.type }})</span>
</div>
<DeleteDialog
v-if="groupUser.type === 'direct'"
:name="groupUser.name"
singular="Membership"
@delete="removeGroupUserMutation.mutate(groupUser.id)"
>
<Button variant="ghost" size="icon" class="h-8 w-8">
<Trash2 class="size-4" />
</Button>
</DeleteDialog>
</PanelListElement>
<div
v-if="!groupUsers || groupUsers.length === 0"
class="flex h-10 items-center p-4 text-muted-foreground"
>
No users assigned yet.
</div>
</TicketPanel>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Inheritance</CardTitle>
</CardHeader>
<CardContent>
<div class="mt-4 flex flex-col gap-4">
<TicketPanel title="Parent Groups" @add="dialogOpenParent = true">
<GroupSelectDialog
v-model="dialogOpenParent"
@select="selectParent"
:exclude="parentGroups?.map((group) => group.id).concat([id]) ?? [id]"
/>
<PanelListElement
v-for="groupGroup in parentGroups"
:key="groupGroup.id"
class="flex h-10 flex-row items-center pr-1"
>
<div class="flex flex-1 items-center overflow-hidden">
<RouterLink
:to="{ name: 'groups', params: { id: groupGroup.id } }"
class="hover:underline"
>
{{ groupGroup.name }}
</RouterLink>
<span class="ml-1 text-sm text-muted-foreground">({{ groupGroup.type }})</span>
</div>
<DeleteDialog
v-if="groupGroup.type === 'direct'"
:name="groupGroup.name"
singular="Inheritance"
@delete="removeGroupParentMutation.mutate(groupGroup.id)"
>
<Button variant="ghost" size="icon" class="h-8 w-8">
<Trash2 class="size-4" />
</Button>
</DeleteDialog>
</PanelListElement>
<div
v-if="!parentGroups || parentGroups.length === 0"
class="flex h-10 items-center p-4 text-muted-foreground"
>
No groups assigned yet.
</div>
</TicketPanel>
</div>
<div class="mt-4 flex flex-col gap-4">
<h2 class="text-sm font-medium">Permissions</h2>
<p class="text-sm text-muted-foreground">
The following permissions are granted in addition to the permissions selected to the left
by the parent groups.
</p>
<div class="flex flex-wrap gap-2">
<Badge v-for="(permission, index) in parentPermissions" :key="index">{{
permission
}}</Badge>
</div>
</div>
</CardContent>
</Card>
</template>

View File

@@ -0,0 +1,60 @@
<script setup lang="ts">
import TanView from '@/components/TanView.vue'
import ColumnHeader from '@/components/layout/ColumnHeader.vue'
import ResourceListElement from '@/components/layout/ResourceListElement.vue'
import { Button } from '@/components/ui/button'
import { useQuery } from '@tanstack/vue-query'
import { useRoute, useRouter } from 'vue-router'
import { useAPI } from '@/api'
import type { Group } from '@/client/models'
const api = useAPI()
const route = useRoute()
const router = useRouter()
const {
isPending,
isError,
data: groups,
error
} = useQuery({
queryKey: ['groups'],
queryFn: (): Promise<Array<Group>> => api.listGroups()
})
const description = (group: Group): string => {
return group.permissions.join(', ')
}
const openNew = () => {
router.push({ name: 'groups', params: { id: 'new' } })
}
</script>
<template>
<TanView :isError="isError" :isPending="isPending" :error="error">
<ColumnHeader title="Groups" show-sidebar-trigger>
<div class="ml-auto">
<Button variant="ghost" @click="openNew">New Group</Button>
</div>
</ColumnHeader>
<div class="mt-2 flex flex-1 flex-col gap-2 overflow-auto p-2 pt-0">
<ResourceListElement
v-for="group in groups"
:key="group.id"
:title="group.name"
:created="group.created"
subtitle=""
:description="description(group)"
:active="route.params.id === group.id"
:to="{ name: 'groups', params: { id: group.id } }"
:open="false"
>
{{ group.name }}
</ResourceListElement>
</div>
</TanView>
</template>

View File

@@ -0,0 +1,51 @@
<script setup lang="ts">
import GroupForm from '@/components/group/GroupForm.vue'
import ColumnBody from '@/components/layout/ColumnBody.vue'
import ColumnBodyContainer from '@/components/layout/ColumnBodyContainer.vue'
import ColumnHeader from '@/components/layout/ColumnHeader.vue'
import { Button } from '@/components/ui/button'
import { useToast } from '@/components/ui/toast/use-toast'
import { ChevronLeft } from 'lucide-vue-next'
import { useMutation, useQueryClient } from '@tanstack/vue-query'
import { useRouter } from 'vue-router'
import { useAPI } from '@/api'
import type { Group, NewGroup } from '@/client'
import { handleError } from '@/lib/utils'
const api = useAPI()
const queryClient = useQueryClient()
const router = useRouter()
const { toast } = useToast()
const addGroupMutation = useMutation({
mutationFn: (values: NewGroup): Promise<Group> => api.createGroup({ newGroup: values }),
onSuccess: (data: Group) => {
router.push({ name: 'groups', params: { id: data.id } })
toast({
title: 'Group created',
description: 'The group has been created successfully'
})
queryClient.invalidateQueries({ queryKey: ['groups'] })
},
onError: handleError('Failed to create group')
})
</script>
<template>
<ColumnHeader>
<Button @click="router.push({ name: 'groups' })" variant="outline" class="md:hidden">
<ChevronLeft class="mr-2 size-4" />
Back
</Button>
</ColumnHeader>
<ColumnBody>
<ColumnBodyContainer small>
<GroupForm @submit="addGroupMutation.mutate" />
</ColumnBodyContainer>
</ColumnBody>
</template>

View File

@@ -0,0 +1,115 @@
<script setup lang="ts">
import { Button } from '@/components/ui/button'
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle
} from '@/components/ui/dialog'
import { FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue
} from '@/components/ui/select'
import { useQuery } from '@tanstack/vue-query'
import { defineRule, useForm } from 'vee-validate'
import { computed, ref, watch } from 'vue'
import { useAPI } from '@/api'
import type { Group } from '@/client'
const api = useAPI()
const isOpen = defineModel<boolean>()
const props = defineProps<{
exclude: Array<string>
}>()
const emit = defineEmits(['select'])
const { data: groups } = useQuery({
queryKey: ['groups'],
queryFn: (): Promise<Array<Group>> => api.listGroups()
})
const filteredGroups = computed(() => {
return groups.value?.filter((group) => !props.exclude.includes(group.id)) ?? []
})
defineRule('required', (value: string) => {
if (!value || !value.length) {
return 'This field is required'
}
return true
})
const { handleSubmit, validate, values } = useForm({
validationSchema: {
group: 'required'
}
})
const onSubmit = handleSubmit((values) => emit('select', values))
const submitDisabled = ref(true)
const change = () => validate({ mode: 'silent' }).then((res) => (submitDisabled.value = !res.valid))
watch(
() => values,
() => change(),
{ deep: true, immediate: true }
)
</script>
<template>
<Dialog v-model:open="isOpen">
<DialogContent>
<DialogHeader>
<DialogTitle>New Group</DialogTitle>
<DialogDescription> Add a new group to this user</DialogDescription>
</DialogHeader>
<form @submit="onSubmit" @change="change">
<FormField name="group" v-slot="{ componentField }">
<FormItem>
<FormLabel for="group" class="text-right"> Group</FormLabel>
<Select id="group" v-bind="componentField">
<SelectTrigger>
<SelectValue placeholder="Select a group" />
</SelectTrigger>
<SelectContent>
<SelectItem v-for="group in filteredGroups" :key="group.id" :value="group.id"
>{{ group.name }}
</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
</FormField>
<DialogFooter class="mt-2 sm:justify-start">
<Button
:title="submitDisabled ? 'Please fill out all required fields' : undefined"
:disabled="submitDisabled"
type="submit"
>
Save
</Button>
<DialogClose as-child>
<Button type="button" variant="secondary"> Cancel</Button>
</DialogClose>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
</template>

View File

@@ -1,5 +1,19 @@
<script setup lang="ts">
import { type HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<div class="flex flex-1 items-start justify-start overflow-y-auto overflow-x-hidden">
<div
:class="
cn('flex flex-1 items-start justify-start overflow-y-auto overflow-x-hidden', props.class)
"
>
<slot />
</div>
</template>

View File

@@ -7,7 +7,9 @@ defineProps<{
</script>
<template>
<div :class="cn('mx-auto flex w-full max-w-[72rem] gap-4 p-4', small && 'max-w-[47rem]')">
<div
:class="cn('mx-auto flex w-full max-w-[72rem] flex-col gap-4 p-4', small && 'max-w-[47rem]')"
>
<slot />
</div>
</template>

View File

@@ -1,9 +1,11 @@
<script setup lang="ts">
import { Separator } from '@/components/ui/separator'
import { SidebarTrigger } from '@/components/ui/sidebar'
import { cn } from '@/lib/utils'
defineProps<{
showSidebarTrigger?: boolean
title?: string
nowrap?: boolean
hideSeparator?: boolean
@@ -16,6 +18,7 @@ defineProps<{
cn('flex min-h-14 flex-wrap items-center gap-2 bg-background p-2', nowrap && 'flex-nowrap')
"
>
<SidebarTrigger v-if="showSidebarTrigger" />
<h1 v-if="title" class="text-xl font-bold">
{{ title }}
</h1>

View File

@@ -1,13 +1,16 @@
<script setup lang="ts">
import Icon from '@/components/Icon.vue'
import { formatDistanceToNow } from 'date-fns'
import { cn } from '@/lib/utils'
defineProps<{
icon?: string
title: string
subtitle: string
description: string
created: string
created: Date
open: boolean
active: boolean
@@ -27,14 +30,15 @@ defineProps<{
>
<div class="flex w-full flex-col gap-1">
<div class="flex items-center">
<div class="flex items-center gap-2">
<div class="flex items-center gap-1">
<Icon v-if="icon" :name="icon" class="mr-2 size-4" />
<div class="font-semibold">
{{ title }}
</div>
<span v-if="open" class="flex h-2 w-2 rounded-full bg-blue-600" />
<span v-if="open" class="ml-1 flex h-2 w-2 rounded-full bg-blue-600" />
</div>
<div :class="cn('ml-auto text-xs', active ? 'text-foreground' : 'text-muted-foreground')">
{{ formatDistanceToNow(new Date(created), { addSuffix: true }) }}
{{ formatDistanceToNow(created, { addSuffix: true }) }}
</div>
</div>

View File

@@ -1,85 +1,205 @@
<script setup lang="ts">
import Icon from '@/components/Icon.vue'
import CatalystLogo from '@/components/common/CatalystLogo.vue'
import IncidentNav from '@/components/sidebar/IncidentNav.vue'
import NavList from '@/components/sidebar/NavList.vue'
import UserDropDown from '@/components/sidebar/UserDropDown.vue'
import { Button } from '@/components/ui/button'
import { Separator } from '@/components/ui/separator'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger
} from '@/components/ui/dropdown-menu'
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupLabel,
SidebarHeader,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarRail
} from '@/components/ui/sidebar'
import { Menu } from 'lucide-vue-next'
import { ChevronsUpDown, LogOut, Settings, Tag, User, Users, Zap } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
import { useCatalystStore } from '@/store/catalyst'
import { useQuery } from '@tanstack/vue-query'
import { computed } from 'vue'
import { useRouter } from 'vue-router'
const catalystStore = useCatalystStore()
import { useAPI } from '@/api.ts'
import type { Sidebar as SidebarModel } from '@/client/models'
import { useAuthStore } from '@/store/auth'
const authStore = useAuthStore()
const links = [
{
name: 'Reactions',
url: '/reactions',
icon: Zap,
permission: 'reaction:write'
},
{
name: 'Users',
url: '/users',
icon: User,
permission: 'group:write'
},
{
name: 'Groups',
url: '/groups',
icon: Users,
permission: 'group:write'
},
{
name: 'Types',
url: '/types',
icon: Tag,
permission: 'type:write'
},
{
name: 'Settings',
url: '/settings',
icon: Settings,
permission: 'settings:write'
}
]
const userLinks = computed(() => {
return links.filter((link) => authStore.hasPermission(link.permission))
})
const api = useAPI()
const router = useRouter()
const { data: sidebar } = useQuery({
queryKey: ['sidebar'],
queryFn: (): Promise<Array<SidebarModel>> => api.getSidebar()
})
const logout = () => {
authStore.setToken('')
router.push({ name: 'login' })
}
const initials = (user: { name?: string } | undefined) => {
if (!user || !user.name) return ''
const names = user.name.split(' ')
return names.length > 1 ? `${names[0][0]}${names[1][0]}` : names[0][0]
}
</script>
<template>
<div
:class="
cn(
'flex min-w-48 shrink-0 flex-col border-r bg-popover', // transition-all duration-300 ease-in-out',
catalystStore.sidebarCollapsed && 'min-w-[50px]'
)
"
>
<div class="flex h-[57px] items-center border-b bg-background">
<CatalystLogo
class="size-8"
:class="{
'flex-1': catalystStore.sidebarCollapsed,
'mx-3': !catalystStore.sidebarCollapsed
}"
/>
<h1 class="text-xl font-bold" v-if="!catalystStore.sidebarCollapsed">Catalyst</h1>
</div>
<NavList
:is-collapsed="catalystStore.sidebarCollapsed"
:links="[
{
title: 'Dashboard',
icon: 'PanelsTopLeft',
variant: 'ghost',
to: '/dashboard'
}
]"
/>
<Separator />
<IncidentNav :is-collapsed="catalystStore.sidebarCollapsed" />
<div class="flex-1" />
<Separator />
<NavList
:is-collapsed="catalystStore.sidebarCollapsed"
:links="[
{
title: 'Reactions',
icon: 'Zap',
variant: 'ghost',
to: '/reactions'
}
]"
/>
<Separator />
<UserDropDown :is-collapsed="catalystStore.sidebarCollapsed" />
<Separator />
<div :class="cn('flex h-14 items-center px-3', !catalystStore.sidebarCollapsed && 'px-2')">
<Button
variant="ghost"
@click="catalystStore.toggleSidebar()"
size="default"
:class="
cn(
'p-0',
catalystStore.sidebarCollapsed && 'w-9',
!catalystStore.sidebarCollapsed && 'w-full justify-start px-3'
)
"
>
<Menu class="size-4" />
<span v-if="!catalystStore.sidebarCollapsed" class="ml-2">Toggle Sidebar</span>
</Button>
</div>
</div>
<SidebarProvider class="h-full w-full" style="--sidebar-width: 12rem">
<Sidebar collapsible="icon">
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem class="flex items-center gap-2 p-2">
<CatalystLogo :size="5" />
<div class="grid flex-1 text-left text-sm leading-tight">
<span class="truncate font-semibold">Catalyst</span>
<span class="truncate text-xs">Incident Management</span>
</div>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Tickets</SidebarGroupLabel>
<SidebarMenu>
<SidebarMenuItem v-for="(typ, index) of sidebar" :key="index">
<SidebarMenuButton :tooltip="typ.plural" as-child>
<RouterLink :to="`/tickets/${typ.id}`">
<Icon :name="typ.icon" class="size-4" />
<span>{{ typ.plural }}</span>
<span class="ml-auto">{{ typ.count }}</span>
</RouterLink>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroup>
<div class="flex-1" />
<SidebarGroup v-if="userLinks.length > 0" class="group-data-[collapsible=icon]:hidden">
<SidebarGroupLabel>Administration</SidebarGroupLabel>
<SidebarMenu>
<SidebarMenuItem v-for="item in userLinks" :key="item.name">
<SidebarMenuButton as-child>
<RouterLink :to="item.url">
<component :is="item.icon" />
<span>{{ item.name }}</span>
</RouterLink>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<SidebarMenuButton
size="lg"
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
>
<Avatar class="h-8 w-8 rounded-lg">
<AvatarImage
:src="authStore.user?.avatar ? authStore.user.avatar : ''"
:alt="authStore.user?.name"
/>
<AvatarFallback class="rounded-lg"
>{{ initials(authStore.user) }}
</AvatarFallback>
</Avatar>
<div class="grid flex-1 text-left text-sm leading-tight">
<span class="truncate font-semibold">{{ authStore.user?.name }}</span>
<span class="truncate text-xs">{{ authStore.user?.email }}</span>
</div>
<ChevronsUpDown class="ml-auto size-4" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
class="w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg"
side="bottom"
align="end"
:side-offset="4"
>
<DropdownMenuLabel class="p-0 font-normal">
<div class="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
<Avatar class="h-8 w-8 rounded-lg">
<AvatarImage
:src="authStore.user?.avatar ? authStore.user.avatar : ''"
:alt="authStore.user?.name"
/>
<AvatarFallback class="rounded-lg"
>{{ initials(authStore.user) }}
</AvatarFallback>
</Avatar>
<div class="grid flex-1 text-left text-sm leading-tight">
<span class="truncate font-semibold">{{ authStore.user?.name }}</span>
<span class="truncate text-xs">{{ authStore.user?.email }}</span>
</div>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem @click="logout">
<LogOut />
Log out
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</SidebarFooter>
<SidebarRail />
</Sidebar>
<SidebarInset class="flex h-full w-full">
<slot />
</SidebarInset>
</SidebarProvider>
</template>

View File

@@ -11,30 +11,19 @@ defineProps<{
<template>
<TooltipProvider :delay-duration="0">
<div class="flex h-full flex-row items-stretch bg-muted/40">
<SideBar />
<div
:class="
cn(
'w-full flex-initial border-r sm:w-72',
!showDetails && 'flex',
showDetails && 'hidden sm:flex'
)
"
>
<div class="flex h-full w-full flex-col">
<SideBar>
<div class="flex h-full w-full flex-col overflow-auto md:flex-row">
<div
:class="
cn('flex h-full w-full flex-col border-r md:w-72', showDetails ? 'hidden md:flex' : '')
"
>
<slot name="list" />
</div>
</div>
<div
:class="
cn('flex-1 overflow-hidden', !showDetails && 'hidden sm:flex', showDetails && 'flex')
"
>
<div class="flex h-full w-full flex-1 flex-col">
<div :class="cn('flex h-full w-full flex-1 flex-col', showDetails ? '' : 'hidden md:flex')">
<slot name="single" />
</div>
</div>
</div>
</SideBar>
</TooltipProvider>
</template>

View File

@@ -5,11 +5,8 @@ import { TooltipProvider } from '@/components/ui/tooltip'
<template>
<TooltipProvider :delay-duration="0">
<div class="flex h-full flex-row items-stretch bg-muted/40">
<SideBar />
<div class="flex h-full w-full flex-col">
<slot />
</div>
</div>
<SideBar>
<slot />
</SideBar>
</TooltipProvider>
</template>

View File

@@ -6,20 +6,22 @@ import ColumnBodyContainer from '@/components/layout/ColumnBodyContainer.vue'
import ColumnHeader from '@/components/layout/ColumnHeader.vue'
import ReactionForm from '@/components/reaction/ReactionForm.vue'
import { Button } from '@/components/ui/button'
import { toast } from '@/components/ui/toast'
import { useToast } from '@/components/ui/toast/use-toast'
import { ChevronLeft } from 'lucide-vue-next'
import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query'
import { onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { pb } from '@/lib/pocketbase'
import type { Reaction } from '@/lib/types'
import { useAPI } from '@/api'
import type { Reaction } from '@/client/models'
import { handleError } from '@/lib/utils'
const api = useAPI()
const router = useRouter()
const queryClient = useQueryClient()
const { toast } = useToast()
const props = defineProps<{
id: string
@@ -32,65 +34,49 @@ const {
error
} = useQuery({
queryKey: ['reactions', props.id],
queryFn: (): Promise<Reaction> => pb.collection('reactions').getOne(props.id)
queryFn: (): Promise<Reaction> => api.getReaction({ id: props.id })
})
const updateReactionMutation = useMutation({
mutationFn: (update: any) => pb.collection('reactions').update(props.id, update),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['reactions'] }),
onError: handleError
})
onMounted(() => {
if (props.id) {
pb.collection('reactions').subscribe(props.id, (data) => {
if (data.action === 'delete') {
toast({
title: 'Reaction deleted',
description: 'The reaction has been deleted.',
variant: 'destructive'
})
router.push({ name: 'reactions' })
return
}
if (data.action === 'update') {
toast({
title: 'Reaction updated',
description: 'The reaction has been updated.'
})
queryClient.invalidateQueries({ queryKey: ['reactions', props.id] })
}
mutationFn: (update: any) => api.updateReaction({ id: props.id, reactionUpdate: update }),
onSuccess: () => {
toast({
title: 'Reaction updated',
description: 'The reaction has been updated successfully'
})
}
queryClient.invalidateQueries({ queryKey: ['reactions'] })
},
onError: handleError('Failed to update reaction')
})
onUnmounted(() => {
if (props.id) {
pb.collection('reactions').unsubscribe(props.id)
}
const deleteMutation = useMutation({
mutationFn: () => api.deleteReaction({ id: props.id }),
onSuccess: () => {
queryClient.removeQueries({ queryKey: ['reactions', props.id] })
queryClient.invalidateQueries({ queryKey: ['reactions'] })
toast({
title: 'Reaction deleted',
description: 'The reaction has been deleted successfully'
})
router.push({ name: 'reactions' })
},
onError: handleError('Failed to delete reaction')
})
</script>
<template>
<TanView :isError="isError" :isPending="isPending" :error="error">
<ColumnHeader>
<Button @click="router.push({ name: 'reactions' })" variant="outline" class="sm:hidden">
<Button @click="router.push({ name: 'reactions' })" variant="outline" class="md:hidden">
<ChevronLeft class="mr-2 size-4" />
Back
</Button>
<div class="ml-auto">
<DeleteDialog
v-if="reaction"
collection="reactions"
:id="reaction.id"
:name="reaction.name"
:singular="'Reaction'"
:to="{ name: 'reactions' }"
:queryKey="['reactions']"
singular="Reaction"
@delete="deleteMutation.mutate"
/>
</div>
</ColumnHeader>

View File

@@ -31,8 +31,10 @@ import { useQuery } from '@tanstack/vue-query'
import { defineRule, useForm } from 'vee-validate'
import { computed, ref, watch } from 'vue'
import { pb } from '@/lib/pocketbase'
import type { Reaction } from '@/lib/types'
import { useAPI } from '@/api'
import type { Reaction } from '@/client/models'
const api = useAPI()
const submitDisabledReason = ref<string>('')
@@ -46,14 +48,14 @@ const isDemo = ref(false)
const { data: config } = useQuery({
queryKey: ['config'],
queryFn: (): Promise<Record<string, Array<String>>> => pb.send('/api/config', {})
queryFn: () => api.getConfig()
})
watch(
() => config.value,
() => {
if (!config.value) return
if (config.value['flags'].includes('demo')) {
if (config.value.flags.includes('demo')) {
isDemo.value = true
}
},
@@ -87,7 +89,7 @@ defineRule('triggerdata.expression', (value: string) => {
return 'Invalid cron expression'
})
defineRule('triggerdata.token', (value: string) => {
defineRule('triggerdata.token', () => {
return true
})
@@ -251,8 +253,10 @@ const curlExample = computed(() => {
cmd += ` -H "Authorization: Bearer ${values.triggerdata.token}"`
}
const url = `${location.protocol}//${location.hostname}:${location.port}`
if (values.triggerdata.path) {
cmd += ` https://${location.hostname}/reaction/${values.triggerdata.path}`
cmd += ` -d '{"foo":"bar"}' ${url}/reaction/${values.triggerdata.path}`
}
return cmd
@@ -304,8 +308,8 @@ const curlExample = computed(() => {
<TriggerHookFormFields v-else-if="values.trigger === 'hook'" />
<div v-if="values.trigger === 'webhook'">
<Label for="url">Usage</Label>
<Input id="url" readonly :modelValue="curlExample" class="bg-accent" />
<Label for="usage">Usage</Label>
<Input id="usage" readonly :modelValue="curlExample" class="bg-accent" />
</div>
</CardContent>
</Card>

Some files were not shown because too many files have changed in this diff Show More