mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-22 16:34:26 +01:00
Custom Forms: Allow HTML in labels and help text (#5136)
* Custom Forms: Allow HTML in labels and help text Fixes #5003. * Vue: Sanitize labels and helper text input * Form editor: Fix blur on input for select option values --------- Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
This commit is contained in:
@@ -390,6 +390,11 @@ retry:
|
|||||||
version = Regex.Match(actual, "BootstrapVue ([0-9]+.[0-9]+.[0-9]+)").Groups[1].Value;
|
version = Regex.Match(actual, "BootstrapVue ([0-9]+.[0-9]+.[0-9]+)").Groups[1].Value;
|
||||||
expected = (await (await client.GetAsync($"https://cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/{version}/bootstrap-vue.min.js")).Content.ReadAsStringAsync()).Trim();
|
expected = (await (await client.GetAsync($"https://cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/{version}/bootstrap-vue.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||||
EqualJsContent(expected, actual);
|
EqualJsContent(expected, actual);
|
||||||
|
|
||||||
|
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "vue-sanitize-directive", "vue-sanitize-directive.umd.min.js").Trim();
|
||||||
|
version = Regex.Match(actual, "Original file: /npm/vue-sanitize-directive@([0-9]+.[0-9]+.[0-9]+)").Groups[1].Value;
|
||||||
|
expected = (await (await client.GetAsync($"https://cdn.jsdelivr.net/npm/vue-sanitize-directive@{version}/dist/vue-sanitize-directive.umd.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||||
|
EqualJsContent(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EqualJsContent(string expected, string actual)
|
private void EqualJsContent(string expected, string actual)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
@if (!Model.Constant)
|
@if (!Model.Constant)
|
||||||
{
|
{
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend class="h3 mt-4 mb-3">@Model.Label</legend>
|
<legend class="h3 mt-4 mb-3">@Safe.Raw(Model.Label)</legend>
|
||||||
@foreach (var field in Model.Fields)
|
@foreach (var field in Model.Fields)
|
||||||
{
|
{
|
||||||
if (FormComponentProviders.TypeToComponentProvider.TryGetValue(field.Type, out var partial) && !string.IsNullOrEmpty(partial.View))
|
if (FormComponentProviders.TypeToComponentProvider.TryGetValue(field.Type, out var partial) && !string.IsNullOrEmpty(partial.View))
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
}
|
}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="@Model.Name"@(Model.Required ? " data-required" : "")>
|
<label class="form-label" for="@Model.Name"@(Model.Required ? " data-required" : "")>
|
||||||
@Model.Label
|
@Safe.Raw(Model.Label)
|
||||||
</label>
|
</label>
|
||||||
<input id="@Model.Name" type="@Model.Type" class="form-control @(errors is null ? "" : "is-invalid")"
|
<input id="@Model.Name" type="@Model.Type" class="form-control @(errors is null ? "" : "is-invalid")"
|
||||||
name="@Model.Name" value="@Model.Value" data-val="true"
|
name="@Model.Name" value="@Model.Value" data-val="true"
|
||||||
|
|||||||
@@ -12,17 +12,15 @@
|
|||||||
}
|
}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="@Model.Name"@(Model.Required ? " data-required" : "")>
|
<label class="form-label" for="@Model.Name"@(Model.Required ? " data-required" : "")>
|
||||||
@Model.Label
|
@Safe.Raw(Model.Label)
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<select id="@selectField.Name" asp-items="selectField.Options" class="form-select @(errors is null ? "" : "is-invalid")"
|
<select id="@selectField.Name" asp-items="selectField.Options" class="form-select @(errors is null ? "" : "is-invalid")"
|
||||||
name="@selectField.Name" data-val="true" aria-describedby="HelpText-@selectField.Name" required="@selectField.Required"
|
name="@selectField.Name" data-val="true" aria-describedby="HelpText-@selectField.Name" required="@selectField.Required"
|
||||||
data-val-required="@selectField.Label is required.">
|
data-val-required="@selectField.Label is required.">
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<span class="text-danger" data-valmsg-for="@selectField.Name" data-valmsg-replace="true">@(isInvalid && errors.Any() ? errors.First().ErrorMessage : string.Empty)</span>
|
<span class="text-danger" data-valmsg-for="@selectField.Name" data-valmsg-replace="true">@(isInvalid && errors.Any() ? errors.First().ErrorMessage : string.Empty)</span>
|
||||||
@if (!string.IsNullOrEmpty(selectField.HelpText))
|
@if (!string.IsNullOrEmpty(selectField.HelpText))
|
||||||
{
|
{
|
||||||
<div id="@($"HelpText-{selectField.Name}")" class="form-text">@selectField.HelpText</div>
|
<div id="@($"HelpText-{selectField.Name}")" class="form-text">@Safe.Raw(selectField.HelpText)</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
}
|
}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="@Model.Name"@(Model.Required ? " data-required" : "")>
|
<label class="form-label" for="@Model.Name"@(Model.Required ? " data-required" : "")>
|
||||||
@Model.Label
|
@Safe.Raw(Model.Label)
|
||||||
</label>
|
</label>
|
||||||
<textarea id="@Model.Name" class="form-control @(errors is null ? "" : "is-invalid")"
|
<textarea id="@Model.Name" class="form-control @(errors is null ? "" : "is-invalid")"
|
||||||
name="@Model.Name" data-val="true"
|
name="@Model.Name" data-val="true"
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<div class="field flex-grow-1">
|
<div class="field flex-grow-1">
|
||||||
<label :for="`field-option-value-${index}`" class="form-label">Value</label>
|
<label :for="`field-option-value-${index}`" class="form-label">Value</label>
|
||||||
<input :for="`field-option-value-${index}`" class="form-control" v-model="option.value" />
|
<input :for="`field-option-value-${index}`" class="form-control" v-model.lazy="option.value" />
|
||||||
</div>
|
</div>
|
||||||
<div class="field flex-grow-1">
|
<div class="field flex-grow-1">
|
||||||
<label :for="`field-option-text-${index}`" class="form-label">Text</label>
|
<label :for="`field-option-text-${index}`" class="form-label">Text</label>
|
||||||
@@ -122,25 +122,25 @@
|
|||||||
</template>
|
</template>
|
||||||
<template id="field-type-input">
|
<template id="field-type-input">
|
||||||
<div class="form-group mb-0">
|
<div class="form-group mb-0">
|
||||||
<label class="form-label" :for="name" :data-required="required" v-text="label"></label>
|
<label class="form-label" :for="name" :data-required="required" v-sanitize="label"></label>
|
||||||
<input class="form-control" :id="name" :name="name" :type="type" v-model="value" />
|
<input class="form-control" :id="name" :name="name" :type="type" v-model="value" />
|
||||||
<div v-if="helpText" :id="`HelpText-{name}`" class="form-text" v-text="helpText"></div>
|
<div v-if="helpText" :id="`HelpText-{name}`" class="form-text" v-sanitize="helpText"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template id="field-type-textarea">
|
<template id="field-type-textarea">
|
||||||
<div class="form-group mb-0">
|
<div class="form-group mb-0">
|
||||||
<label class="form-label" :for="name" :data-required="required" v-text="label"></label>
|
<label class="form-label" :for="name" :data-required="required" v-sanitize="label"></label>
|
||||||
<textarea class="form-control" :id="name" :name="name" v-model="value"></textarea>
|
<textarea class="form-control" :id="name" :name="name" v-model="value"></textarea>
|
||||||
<div v-if="helpText" :id="`HelpText-${name}`" class="form-text" v-text="helpText"></div>
|
<div v-if="helpText" :id="`HelpText-${name}`" class="form-text" v-sanitize="helpText"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template id="field-type-select">
|
<template id="field-type-select">
|
||||||
<div class="form-group mb-0">
|
<div class="form-group mb-0">
|
||||||
<label class="form-label" :for="name" :data-required="required" v-text="label"></label>
|
<label class="form-label" :for="name" :data-required="required" v-sanitize="label"></label>
|
||||||
<select class="form-select" :id="name" :name="name">
|
<select class="form-select" :id="name" :name="name">
|
||||||
<option v-for="option in options" :key="option.value" :value="option.value" :selected="option.value === value" v-text="option.text"></option>
|
<option v-for="option in options" :key="option.value" :value="option.value" :selected="option.value === value" v-text="option.text"></option>
|
||||||
</select>
|
</select>
|
||||||
<div v-if="helpText" :id="`HelpText-${name}`" class="form-text" v-text="helpText"></div>
|
<div v-if="helpText" :id="`HelpText-${name}`" class="form-text" v-sanitize="helpText"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template id="field-type-fieldset">
|
<template id="field-type-fieldset">
|
||||||
@@ -150,6 +150,7 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
</template>
|
</template>
|
||||||
<script src="~/vendor/vuejs/vue.min.js" asp-append-version="true"></script>
|
<script src="~/vendor/vuejs/vue.min.js" asp-append-version="true"></script>
|
||||||
|
<script src="~/vendor/vue-sanitize-directive/vue-sanitize-directive.umd.min.js" asp-append-version="true"></script>
|
||||||
<script src="~/vendor/vue-sortable/sortable.min.js" asp-append-version="true"></script>
|
<script src="~/vendor/vue-sortable/sortable.min.js" asp-append-version="true"></script>
|
||||||
<script src="~/vendor/vue-sortable/vue-sortable.js" asp-append-version="true"></script>
|
<script src="~/vendor/vue-sortable/vue-sortable.js" asp-append-version="true"></script>
|
||||||
<script src="~/js/form-editor.js" asp-append-version="true"></script>
|
<script src="~/js/form-editor.js" asp-append-version="true"></script>
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Vue.use(vSortable)
|
Vue.use(vSortable)
|
||||||
|
Vue.use(VueSanitizeDirective.default)
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
el: '#FormEditor',
|
el: '#FormEditor',
|
||||||
|
|||||||
52
BTCPayServer/wwwroot/vendor/vue-sanitize-directive/vue-sanitize-directive.umd.min.js
vendored
Normal file
52
BTCPayServer/wwwroot/vendor/vue-sanitize-directive/vue-sanitize-directive.umd.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user