Files
openobserve/web/src/components/CopyContent.vue
T

156 lines
5.1 KiB
Vue

<!-- Copyright 2026 OpenObserve Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<template>
<!-- an empty passcode would substitute into a valid-looking but non-functional snippet -->
<OBanner
v-if="passcodeForbidden && contentNeedsPasscode"
variant="warning"
data-test="copy-content-passcode-forbidden"
:content="t('ingestion.passcodeForbiddenMessage')"
/>
<div v-else class="rounded-default copy-content-block bg-surface-subtle relative overflow-hidden">
<div class="absolute top-2 right-2 z-10">
<OButton
data-test="rum-copy-btn"
variant="ghost"
size="icon-xs-sq"
@click="copyToClipboardFn()"
>
<OIcon name="content-copy" size="sm" />
<OTooltip :content="t('common.copy')" side="top" />
</OButton>
</div>
<pre
data-test="rum-content-text"
class="m-0 p-3 pe-10 text-sm leading-5 wrap-break-word whitespace-pre-wrap"
>{{ computedContent }}</pre>
</div>
</template>
<script lang="ts">
// @ts-nocheck
import { defineComponent, ref, type PropType } from "vue";
import { type I18nText, useI18nTyped } from "@/types/i18n";
import { useStore } from "vuex";
import { useRouter } from "vue-router";
import { copyToClipboard } from "@/utils/clipboard";
import analytics from "@/services/product_analytics";
import { maskText, b64EncodeStandard } from "../utils/zincutils";
import OButton from "@/lib/core/Button/OButton.vue";
import OIcon from "@/lib/core/Icon/OIcon.vue";
import OTooltip from "@/lib/overlay/Tooltip/OTooltip.vue";
import OBanner from "@/lib/feedback/Banner/OBanner.vue";
const PASSCODE_PLACEHOLDERS = ["[PASSCODE]", "[BASIC_PASSCODE]"];
export default defineComponent({
name: "CopyContent",
components: { OButton, OIcon, OTooltip, OBanner },
props: {
content: {
type: String as unknown as PropType<I18nText>,
default: "", // Default value for content prop (empty string in this case)
},
displayContent: {
type: String,
default: "", // Default value for displayContent prop (empty string in this case)
},
},
setup(props) {
const store = useStore();
const router = useRouter();
const { t } = useI18nTyped();
const email = ref(store.state.userInfo.email);
const passcode = ref(store.state.organizationData.organizationPasscode);
const basicPasscode = ref();
const replaceValues = (data: string, isMask: boolean = false) => {
email.value = store.state.userInfo.email;
passcode.value = store.state.organizationData.organizationPasscode;
basicPasscode.value = b64EncodeStandard(
`${email.value}:${store.state.organizationData.organizationPasscode}`,
);
if (isMask) {
return data
.replaceAll("[EMAIL]", maskText(email.value))
.replaceAll("[PASSCODE]", maskText(passcode.value))
.replaceAll("[BASIC_PASSCODE]", maskText(basicPasscode.value));
} else {
return data
.replaceAll("[EMAIL]", email.value)
.replaceAll("[PASSCODE]", passcode.value)
.replaceAll("[BASIC_PASSCODE]", basicPasscode.value);
}
};
const copyToClipboardFn = () => {
const content = replaceValues(props.content, false);
copyToClipboard(content, t, {
successMessage: t("common.contentCopiedSuccessfully"),
errorMessage: t("common.copyContentError"),
timeout: 5000,
}).then((copied) => {
if (copied) {
analytics.track("snippet_copied", {
route: router?.currentRoute.value.name,
});
}
});
};
const displayData = ref(props.displayContent || props.content);
const computedContent = ref();
computedContent.value = replaceValues(displayData.value, true);
const refreshData = () => {
computedContent.value = replaceValues(displayData.value, true);
};
return {
t,
store,
copyToClipboardFn,
displayData,
replaceValues,
computedContent,
refreshData,
};
},
computed: {
computedData() {
return this.store.state.organizationData.organizationPasscode;
},
passcodeForbidden() {
return !!this.store.state.organizationData.organizationPasscodeForbidden;
},
contentNeedsPasscode() {
const source = this.displayContent || this.content || "";
return PASSCODE_PLACEHOLDERS.some((token) => source.includes(token));
},
},
watch: {
content(newVal: string) {
this.displayData = newVal;
this.refreshData();
},
computedData() {
this.refreshData();
},
},
});
</script>