Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"[docs/public/cfg/service_desk.yml]": {
"files.trimTrailingWhitespace": false,
"editor.tabSize": 2,
"editor.defaultFormatter": null
"editor.defaultFormatter": null,
"editor.formatOnSave": false
}
}
284 changes: 163 additions & 121 deletions docs/.vitepress/theme/components/legacy/ServiceDesk.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ defineOptions({
name: "ServiceDesk",
})

import nunjucksEnv from "../../plugins/nunjucks"

// Emits definition
const emit = defineEmits(["update:modelValue"])

Expand Down Expand Up @@ -41,6 +43,12 @@ const finalizeClicked = ref(false)
const panel = ref(0)

// Computed properties
const templateContext = computed(() => {
return {
...formData.value,
}
})

const messageSubject = computed(() => {
return subjectTemplate.value ? wrap(subjectTemplate.value) : null
})
Expand All @@ -50,7 +58,23 @@ const messageBody = computed(() => {
})

const formFilled = computed(() => {
return props.fields.every((item) => (formData.value[item.key] || item.optional ? true : false))
return props.fields.every((item) => {
if (item.hide) {
if (isFieldHidden(item)) {
return true
}
}

if (formData.value[item.key]) {
return true
}

if (typeof item.optional === "string") {
return evalDynamicField(item.optional)
}

return item.optional
})
})

const encodedSubject = computed(() => {
Expand Down Expand Up @@ -89,6 +113,24 @@ const deeplinkUrl = computed(() => {
})

// Methods
const evalDynamicField = (expr) => {
try {
const dynamicLambda = new Function(`return ${expr}`)()
return dynamicLambda(formData.value)
} catch (ex) {
console.log("Failed to evaluate dynamic field condition", ex)
return false
}
}

const isFieldHidden = (item) => {
if (!item) return false
if (typeof item.hide === "string") {
return evalDynamicField(item.hide, item)
}
return !!item.hide
}

const close = () => {
finalizeClicked.value = true
sendClicked.value = true
Expand All @@ -107,6 +149,9 @@ const activateSendButtons = () => {

const submit = () => {
panel.value = 2
if (props.template) {
bodyTemplate.value = props.template.body
}
setTimeout(activateSendButtons, 1200)
}

Expand Down Expand Up @@ -135,14 +180,10 @@ const actionSendOutlookPopup = () => {

const wrap = (template) => {
let text = template
for (const [key, value] of Object.entries(formData.value)) {
if (value || value === "") {
if (Array.isArray(value)) {
text = text.replaceAll(`{${key}}`, value.join(", "))
} else {
text = text.replaceAll(`{${key}}`, value)
}
}
try {
text = nunjucksEnv.renderString(template, templateContext.value)
} catch (ex) {
console.log("Failed to render template", ex)
}
text = text.replaceAll("\n---\n", "\n```\n")
return text
Expand Down Expand Up @@ -178,7 +219,6 @@ onMounted(() => {
panel.value = 0
loadingEmailButtons.value = true
subjectTemplate.value = props.template ? props.template.subject : null
bodyTemplate.value = props.template ? props.template.body : null

var formFields = []
for (const item of props.fields) {
Expand All @@ -203,7 +243,7 @@ onMounted(() => {
}
}
} catch (ex) {
console.log("Failed to load form fields from cache")
console.log("Failed to load form fields from cache", ex)
}
}
})
Expand Down Expand Up @@ -257,116 +297,118 @@ onMounted(() => {
<v-expansion-panel-text>
<form @submit.prevent="submit">
<v-row justify="center">
<v-col v-for="item in fields" :key="item.key" cols="8">
<v-text-field
v-if="item.field === 'textfield'"
v-model="formData[item.key]"
autocomplete="off"
:label="item.label"
:pattern="item.pattern ? item.pattern : null"
:title="item.hint ? item.hint : null"
:hint="item.hint ? item.hint : null"
:suffix="item.suffix ? item.suffix : null"
:autocapitalize="item.autocapitalize ? item.autocapitalize : null"
:persistent-hint="item.hint && formData[item.key] ? true : false"
placeholder=""
persistent-placeholder
variant="outlined"
density="compact"
:hide-details="formData[item.key] ? false : 'auto'"
@focus="$event.target.select()"
@update:model-value="setValue($event, item.key)"
/>

<v-textarea
v-else-if="item.field === 'textarea'"
v-model="formData[item.key]"
autocomplete="off"
:label="item.label"
:title="item.hint ? item.hint : null"
:hint="item.hint ? item.hint : null"
:suffix="item.suffix ? item.suffix : null"
:autocapitalize="item.autocapitalize ? item.autocapitalize : null"
:rows="item.rows ? item.rows : 3"
:persistent-hint="item.hint && formData[item.key] ? true : false"
placeholder=""
persistent-placeholder
variant="outlined"
density="compact"
:hide-details="formData[item.key] ? false : 'auto'"
@focus="$event.target.select()"
@update:model-value="setValue($event, item.key)"
/>

<v-select
v-else-if="item.field === 'selector'"
:items="item.options"
v-model="formData[item.key]"
:label="item.label"
:item-title="(item) => (Object.prototype.hasOwnProperty.call(item, 'text') ? item.text : item)"
:item-value="(item) => (Object.prototype.hasOwnProperty.call(item, 'value') ? item.value : item)"
placeholder=""
persistent-placeholder
chips
multiple
variant="outlined"
hide-details
/>

<v-select
v-else-if="item.field === 'selectone'"
autocomplete="off"
:items="item.options"
v-model="formData[item.key]"
:label="item.label"
:item-title="(item) => (Object.prototype.hasOwnProperty.call(item, 'text') ? item.text : item)"
:item-value="(item) => (Object.prototype.hasOwnProperty.call(item, 'value') ? item.value : item)"
placeholder=""
persistent-placeholder
chips
variant="outlined"
hide-details
/>

<v-autocomplete
v-else-if="item.field === 'autocompleteone'"
autocomplete="off"
:items="item.options"
v-model="formData[item.key]"
:label="item.label"
:item-title="(item) => (Object.prototype.hasOwnProperty.call(item, 'text') ? item.text : item.header)"
:item-value="(item) => (Object.prototype.hasOwnProperty.call(item, 'value') ? item.value : item)"
placeholder=""
persistent-placeholder
chips
variant="outlined"
density="compact"
clearable
hide-details
/>

<v-text-field
v-else-if="item.field === 'number'"
v-model="formData[item.key]"
autocomplete="off"
type="number"
:label="item.label"
:title="item.hint ? item.hint : null"
:hint="item.hint ? item.hint : null"
:suffix="item.suffix ? item.suffix : null"
:min="item.min ? item.min : null"
:max="item.max ? item.max : null"
:step="item.step ? item.step : null"
:persistent-hint="item.hint && formData[item.key] ? true : false"
placeholder=""
persistent-placeholder
variant="outlined"
density="compact"
:hide-details="formData[item.key] ? false : 'auto'"
@focus="$event.target.select()"
@update:model-value="setValue($event, item.key)"
/>
</v-col>
<template v-for="item in fields" :key="item.key">
<v-col v-if="!isFieldHidden(item)" :key="item.key" cols="8">
<v-text-field
v-if="item.field === 'textfield' && item.type === undefined"
v-model="formData[item.key]"
autocomplete="off"
:label="item.label"
:pattern="item.pattern ? item.pattern : null"
:title="item.hint ? item.hint : null"
:hint="item.hint ? item.hint : null"
:suffix="item.suffix ? item.suffix : null"
:autocapitalize="item.autocapitalize ? item.autocapitalize : null"
:persistent-hint="item.hint && formData[item.key] ? true : false"
placeholder=""
persistent-placeholder
variant="outlined"
density="compact"
:hide-details="formData[item.key] ? false : 'auto'"
@focus="$event.target.select()"
@update:model-value="setValue($event, item.key)"
/>

<v-textarea
v-else-if="item.field === 'textarea'"
v-model="formData[item.key]"
autocomplete="off"
:label="item.label"
:title="item.hint ? item.hint : null"
:hint="item.hint ? item.hint : null"
:suffix="item.suffix ? item.suffix : null"
:autocapitalize="item.autocapitalize ? item.autocapitalize : null"
:rows="item.rows ? item.rows : 3"
:persistent-hint="item.hint && formData[item.key] ? true : false"
placeholder=""
persistent-placeholder
variant="outlined"
density="compact"
:hide-details="formData[item.key] ? false : 'auto'"
@focus="$event.target.select()"
@update:model-value="setValue($event, item.key)"
/>

<v-select
v-else-if="item.field === 'selector'"
:items="item.options"
v-model="formData[item.key]"
:label="item.label"
:item-title="(item) => (Object.prototype.hasOwnProperty.call(item, 'text') ? item.text : item)"
:item-value="(item) => (Object.prototype.hasOwnProperty.call(item, 'value') ? item.value : item)"
placeholder=""
persistent-placeholder
chips
multiple
variant="outlined"
hide-details
/>

<v-select
v-else-if="item.field === 'selectone'"
autocomplete="off"
:items="item.options"
v-model="formData[item.key]"
:label="item.label"
:item-title="(item) => (Object.prototype.hasOwnProperty.call(item, 'text') ? item.text : item)"
:item-value="(item) => (Object.prototype.hasOwnProperty.call(item, 'value') ? item.value : item)"
placeholder=""
persistent-placeholder
chips
variant="outlined"
hide-details
/>

<v-autocomplete
v-else-if="item.field === 'autocompleteone'"
autocomplete="off"
:items="item.options"
v-model="formData[item.key]"
:label="item.label"
:item-title="(item) => (Object.prototype.hasOwnProperty.call(item, 'text') ? item.text : item.header)"
:item-value="(item) => (Object.prototype.hasOwnProperty.call(item, 'value') ? item.value : item)"
placeholder=""
persistent-placeholder
chips
variant="outlined"
density="compact"
clearable
hide-details
/>

<v-text-field
v-else-if="item.field === 'number'"
v-model="formData[item.key]"
autocomplete="off"
type="number"
:label="item.label"
:title="item.hint ? item.hint : null"
:hint="item.hint ? item.hint : null"
:suffix="item.suffix ? item.suffix : null"
:min="item.min ? item.min : null"
:max="item.max ? item.max : null"
:step="item.step ? item.step : null"
:persistent-hint="item.hint && formData[item.key] ? true : false"
placeholder=""
persistent-placeholder
variant="outlined"
density="compact"
:hide-details="formData[item.key] ? false : 'auto'"
@focus="$event.target.select()"
@update:model-value="setValue($event, item.key)"
/>
</v-col>
</template>
</v-row>
<v-row justify="center">
<v-col cols="6">
Expand Down
11 changes: 11 additions & 0 deletions docs/.vitepress/theme/plugins/nunjucks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Library for render Jinja template

import nunjucks from "nunjucks"

const nunjucksEnv = new nunjucks.Environment(null, {
autoescape: false,
trimBlocks: true,
lstripBlocks: true,
})

export default nunjucksEnv
Loading