Files
eveAI/eveai_chat_client/static/assets/vue-components/ConsentRichText.vue
Josako 2b04692fab - TRA-76 - Send Button color changes implemented
- TRA-72 - Translation of privacy statement and T&C
- TRA-73 - Strange characters in Tenant Make Name
- Addition of meta information in Specialist Form Fields
2025-09-15 17:57:13 +02:00

95 lines
2.5 KiB
Vue

<template>
<span class="consent-rich-text">
<template v-for="(node, idx) in nodes" :key="idx">
<component
v-if="node.type !== 'text'"
:is="linkTag"
:href="linkTag === 'a' ? '#' : undefined"
class="consent-link"
:aria-label="node.aria"
role="button"
tabindex="0"
@click.prevent="emitClick(node.type)"
@keydown.enter.prevent="emitClick(node.type)"
@keydown.space.prevent="emitClick(node.type)"
>{{ node.label }}</component>
<span v-else>{{ node.text }}</span>
</template>
</span>
</template>
<script>
export default {
name: 'ConsentRichText',
props: {
template: { type: String, required: true },
asButton: { type: Boolean, default: false },
ariaPrivacy: { type: String, default: 'Open privacy statement in a dialog' },
ariaTerms: { type: String, default: 'Open terms and conditions in a dialog' }
},
emits: ['open-privacy', 'open-terms'],
computed: {
linkTag() {
return this.asButton ? 'button' : 'a';
},
nodes() {
// Parse only allowed tags <privacy>...</privacy> and <terms>...</terms>
const source = (this.template || '');
// 2) parse only allowed tags <privacy>...</privacy> and <terms>...</terms>
const pattern = /<(privacy|terms)>([\s\S]*?)<\/\1>/gi;
const out = [];
let lastIndex = 0;
let match;
while ((match = pattern.exec(source)) !== null) {
const [full, tag, label] = match;
const start = match.index;
if (start > lastIndex) {
out.push({ type: 'text', text: source.slice(lastIndex, start) });
}
out.push({
type: tag, // 'privacy' | 'terms'
label: (label || '').trim(),
aria: tag === 'privacy' ? this.ariaPrivacy : this.ariaTerms
});
lastIndex = start + full.length;
}
if (lastIndex < source.length) {
out.push({ type: 'text', text: source.slice(lastIndex) });
}
return out;
}
},
methods: {
emitClick(kind) {
if (kind === 'privacy') this.$emit('open-privacy');
if (kind === 'terms') this.$emit('open-terms');
}
}
};
</script>
<style scoped>
.consent-link {
color: #007bff;
text-decoration: underline;
cursor: pointer;
transition: color 0.2s ease;
}
.consent-link:hover {
color: #0056b3;
}
.consent-link:focus {
outline: 2px solid #007bff;
outline-offset: 2px;
border-radius: 2px;
}
button.consent-link {
background: none;
border: none;
padding: 0;
color: #007bff;
text-decoration: underline;
}
</style>