feat(redis): custom hover scrollbar for key and value views
This commit is contained in:
12 files changed
+204
-20
No files matched your search
@@ -0,0 +1,184 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { nextTick, onBeforeUnmount, onMounted, ref } from "vue";
|
||||||
|
|
||||||
|
const HIDE_DELAY = 800;
|
||||||
|
|
||||||
|
const scrollRef = ref<HTMLElement>();
|
||||||
|
const trackRef = ref<HTMLElement>();
|
||||||
|
const thumbRef = ref<HTMLElement>();
|
||||||
|
const hasOverflow = ref(false);
|
||||||
|
const isScrolling = ref(false);
|
||||||
|
const isDragging = ref(false);
|
||||||
|
const thumbStyle = ref({ insetInlineStart: "0%", width: "100%" });
|
||||||
|
|
||||||
|
let hideTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
let resizeObserver: ResizeObserver | null = null;
|
||||||
|
let dragState: {
|
||||||
|
pointerOffset: number;
|
||||||
|
trackLeft: number;
|
||||||
|
trackWidth: number;
|
||||||
|
thumbWidth: number;
|
||||||
|
maxScrollLeft: number;
|
||||||
|
} | null = null;
|
||||||
|
|
||||||
|
function clearHideTimer() {
|
||||||
|
if (!hideTimer) return;
|
||||||
|
clearTimeout(hideTimer);
|
||||||
|
hideTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduleHide() {
|
||||||
|
clearHideTimer();
|
||||||
|
hideTimer = setTimeout(() => {
|
||||||
|
isScrolling.value = false;
|
||||||
|
hideTimer = null;
|
||||||
|
}, HIDE_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateMetrics() {
|
||||||
|
const element = scrollRef.value;
|
||||||
|
if (!element) return;
|
||||||
|
|
||||||
|
const maxScrollLeft = Math.max(0, element.scrollWidth - element.clientWidth);
|
||||||
|
hasOverflow.value = maxScrollLeft > 1;
|
||||||
|
if (!hasOverflow.value) {
|
||||||
|
thumbStyle.value = { insetInlineStart: "0%", width: "100%" };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const thumbWidth = Math.min(100, Math.max(10, (element.clientWidth / element.scrollWidth) * 100));
|
||||||
|
const thumbTravel = Math.max(0, 100 - thumbWidth);
|
||||||
|
thumbStyle.value = {
|
||||||
|
insetInlineStart: `${(element.scrollLeft / maxScrollLeft) * thumbTravel}%`,
|
||||||
|
width: `${thumbWidth}%`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function onScroll() {
|
||||||
|
updateMetrics();
|
||||||
|
isScrolling.value = true;
|
||||||
|
scheduleHide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onTrackPointerDown(event: PointerEvent) {
|
||||||
|
const element = scrollRef.value;
|
||||||
|
const track = trackRef.value;
|
||||||
|
const thumb = thumbRef.value;
|
||||||
|
if (!element || !track || !thumb || !hasOverflow.value) return;
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
const trackRect = track.getBoundingClientRect();
|
||||||
|
const thumbRect = thumb.getBoundingClientRect();
|
||||||
|
const pointerOnThumb = event.target === thumb || thumb.contains(event.target as Node);
|
||||||
|
dragState = {
|
||||||
|
pointerOffset: pointerOnThumb ? event.clientX - thumbRect.left : thumbRect.width / 2,
|
||||||
|
trackLeft: trackRect.left,
|
||||||
|
trackWidth: trackRect.width,
|
||||||
|
thumbWidth: thumbRect.width,
|
||||||
|
maxScrollLeft: element.scrollWidth - element.clientWidth,
|
||||||
|
};
|
||||||
|
isDragging.value = true;
|
||||||
|
isScrolling.value = true;
|
||||||
|
window.addEventListener("pointermove", onPointerMove);
|
||||||
|
window.addEventListener("pointerup", stopDragging);
|
||||||
|
window.addEventListener("pointercancel", stopDragging);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPointerMove(event: PointerEvent) {
|
||||||
|
if (!dragState || !scrollRef.value) return;
|
||||||
|
const travel = Math.max(1, dragState.trackWidth - dragState.thumbWidth);
|
||||||
|
const thumbLeft = Math.min(Math.max(event.clientX - dragState.trackLeft - dragState.pointerOffset, 0), travel);
|
||||||
|
scrollRef.value.scrollLeft = (thumbLeft / travel) * dragState.maxScrollLeft;
|
||||||
|
updateMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopDragging() {
|
||||||
|
dragState = null;
|
||||||
|
isDragging.value = false;
|
||||||
|
scheduleHide();
|
||||||
|
window.removeEventListener("pointermove", onPointerMove);
|
||||||
|
window.removeEventListener("pointerup", stopDragging);
|
||||||
|
window.removeEventListener("pointercancel", stopDragging);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
resizeObserver = new ResizeObserver(updateMetrics);
|
||||||
|
if (scrollRef.value) resizeObserver.observe(scrollRef.value);
|
||||||
|
void nextTick(updateMetrics);
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
stopDragging();
|
||||||
|
clearHideTimer();
|
||||||
|
resizeObserver?.disconnect();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="redis-horizontal-scroll-host" :class="{ 'is-scrolling': isScrolling, 'is-dragging': isDragging }">
|
||||||
|
<div ref="scrollRef" class="redis-format-tabs-scroll flex max-w-full overflow-x-auto rounded-md border bg-muted/20 p-0.5" @scroll="onScroll" @mouseenter="updateMetrics">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
<div v-if="hasOverflow" ref="trackRef" class="redis-format-tabs-scrollbar" @pointerdown="onTrackPointerDown">
|
||||||
|
<div class="redis-format-tabs-scrollbar__thumb" :style="thumbStyle" ref="thumbRef" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.redis-horizontal-scroll-host {
|
||||||
|
position: relative;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.redis-format-tabs-scroll {
|
||||||
|
scrollbar-width: none;
|
||||||
|
scrollbar-gutter: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.redis-format-tabs-scroll::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.redis-format-tabs-scrollbar {
|
||||||
|
position: absolute;
|
||||||
|
inset-inline: 0;
|
||||||
|
bottom: 1px;
|
||||||
|
z-index: 2;
|
||||||
|
height: 7px;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
touch-action: none;
|
||||||
|
transition: opacity 140ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.redis-horizontal-scroll-host:hover .redis-format-tabs-scrollbar,
|
||||||
|
.redis-horizontal-scroll-host.is-scrolling .redis-format-tabs-scrollbar,
|
||||||
|
.redis-horizontal-scroll-host.is-dragging .redis-format-tabs-scrollbar {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.redis-format-tabs-scrollbar::before,
|
||||||
|
.redis-format-tabs-scrollbar__thumb {
|
||||||
|
position: absolute;
|
||||||
|
top: 1px;
|
||||||
|
height: 5px;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.redis-format-tabs-scrollbar::before {
|
||||||
|
content: "";
|
||||||
|
inset-inline: 0;
|
||||||
|
background: color-mix(in oklch, var(--foreground) 10%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.redis-format-tabs-scrollbar__thumb {
|
||||||
|
min-width: 20px;
|
||||||
|
background: color-mix(in oklch, var(--foreground) 38%, transparent);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -2382,7 +2382,7 @@ defineExpose({ focusSearch, insertCommand, executeCommand: executeAiCommand });
|
|||||||
<template #default="{ item: row }">
|
<template #default="{ item: row }">
|
||||||
<CustomContextMenu :items="redisKeyContextMenuItems(row.node)" v-slot="{ onContextMenu, isOpen }">
|
<CustomContextMenu :items="redisKeyContextMenuItems(row.node)" v-slot="{ onContextMenu, isOpen }">
|
||||||
<div
|
<div
|
||||||
class="flex items-center gap-2 border-b px-3 text-[13px] cursor-pointer select-none group"
|
class="flex items-center gap-2 border-b px-1.5 text-[13px] cursor-pointer select-none group"
|
||||||
:class="[
|
:class="[
|
||||||
isOpen || (row.node.kind === 'leaf' && selectedKeyRaw === row.node.keyRaw) ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/40',
|
isOpen || (row.node.kind === 'leaf' && selectedKeyRaw === row.node.keyRaw) ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/40',
|
||||||
row.node.kind === 'leaf' ? (isLeafChecked(row.node.keyRaw) && selectedKeyRaw !== row.node.keyRaw ? 'bg-primary/10' : undefined) : groupSelectedCount(row.node) > 0 ? 'bg-primary/10' : undefined,
|
row.node.kind === 'leaf' ? (isLeafChecked(row.node.keyRaw) && selectedKeyRaw !== row.node.keyRaw ? 'bg-primary/10' : undefined) : groupSelectedCount(row.node) > 0 ? 'bg-primary/10' : undefined,
|
||||||
@@ -2391,7 +2391,7 @@ defineExpose({ focusSearch, insertCommand, executeCommand: executeAiCommand });
|
|||||||
@click="onRowClick(row.node, $event)"
|
@click="onRowClick(row.node, $event)"
|
||||||
@contextmenu="(event) => onRedisRowContextMenu(event, row.node, onContextMenu)"
|
@contextmenu="(event) => onRedisRowContextMenu(event, row.node, onContextMenu)"
|
||||||
>
|
>
|
||||||
<div class="min-w-0 flex flex-1 items-center gap-1 overflow-hidden" :style="{ paddingLeft: `${12 + row.depth * 16}px` }">
|
<div class="min-w-0 flex flex-1 items-center gap-1 overflow-hidden" :style="{ paddingLeft: `${4 + row.depth * 10}px` }">
|
||||||
<template v-if="row.node.kind === 'group'">
|
<template v-if="row.node.kind === 'group'">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ import {
|
|||||||
import { decompressRedisValue, decodeBase64RedisValue, decodePickle, decodeProtobuf, isGzipMagic, type RedisDecompressAlgorithm } from "@/lib/redis/codec";
|
import { decompressRedisValue, decodeBase64RedisValue, decodePickle, decodeProtobuf, isGzipMagic, type RedisDecompressAlgorithm } from "@/lib/redis/codec";
|
||||||
import { canFullHighlightRedisText, findRedisTextMatches, nextRedisSearchMatchIndex, REDIS_VALUE_SEARCH_MATCH_LIMIT, renderRedisTextSearchHtml, redisValueSearchStatus } from "@/lib/redis/redisValueSearch";
|
import { canFullHighlightRedisText, findRedisTextMatches, nextRedisSearchMatchIndex, REDIS_VALUE_SEARCH_MATCH_LIMIT, renderRedisTextSearchHtml, redisValueSearchStatus } from "@/lib/redis/redisValueSearch";
|
||||||
import TextContentSearchBar from "@/components/common/TextContentSearchBar.vue";
|
import TextContentSearchBar from "@/components/common/TextContentSearchBar.vue";
|
||||||
|
import RedisHorizontalScrollbar from "@/components/redis/RedisHorizontalScrollbar.vue";
|
||||||
import { decodeJsonUnicodeEscapes, formatJsonSource, mapDisplayToRaw } from "@/lib/common/safeJsonFormat";
|
import { decodeJsonUnicodeEscapes, formatJsonSource, mapDisplayToRaw } from "@/lib/common/safeJsonFormat";
|
||||||
import { unixSecondsToCalendarDateTime } from "@/components/ui/date-time-picker/dateTimePicker";
|
import { unixSecondsToCalendarDateTime } from "@/components/ui/date-time-picker/dateTimePicker";
|
||||||
import { applyRedisExpiryPolicy, type RedisExpiryMode, redisExpiryModeForTtl, validateRedisExpiry } from "@/lib/redis/redisExpiry";
|
import { applyRedisExpiryPolicy, type RedisExpiryMode, redisExpiryModeForTtl, validateRedisExpiry } from "@/lib/redis/redisExpiry";
|
||||||
@@ -97,7 +98,6 @@ const REDIS_AUTO_REFRESH_INTERVAL_STORAGE_KEY = "dbx-redis-auto-refresh-interval
|
|||||||
const REDIS_AUTO_REFRESH_INTERVAL_OPTIONS = [1, 3, 5, 10] as const;
|
const REDIS_AUTO_REFRESH_INTERVAL_OPTIONS = [1, 3, 5, 10] as const;
|
||||||
const REDIS_COLLECTION_ROW_HEIGHT = 32;
|
const REDIS_COLLECTION_ROW_HEIGHT = 32;
|
||||||
const REDIS_STREAM_MIN_ROW_HEIGHT = 96;
|
const REDIS_STREAM_MIN_ROW_HEIGHT = 96;
|
||||||
|
|
||||||
const data = ref<RedisValue | null>(null);
|
const data = ref<RedisValue | null>(null);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const loadingMore = ref(false);
|
const loadingMore = ref(false);
|
||||||
@@ -2804,7 +2804,7 @@ defineExpose({ focusSearch });
|
|||||||
<div v-if="isStringLikeKind && stringValueDetail" class="flex-1 flex flex-col overflow-hidden">
|
<div v-if="isStringLikeKind && stringValueDetail" class="flex-1 flex flex-col overflow-hidden">
|
||||||
<div class="flex h-9 items-center gap-2 border-b px-4 text-xs shrink-0">
|
<div class="flex h-9 items-center gap-2 border-b px-4 text-xs shrink-0">
|
||||||
<span class="shrink-0 text-muted-foreground">{{ t("redis.codecRowLabel") }}</span>
|
<span class="shrink-0 text-muted-foreground">{{ t("redis.codecRowLabel") }}</span>
|
||||||
<div class="flex max-w-full overflow-x-auto rounded-md border bg-muted/20 p-0.5">
|
<RedisHorizontalScrollbar>
|
||||||
<Button
|
<Button
|
||||||
v-for="codec in REDIS_VALUE_CODEC_ORDER"
|
v-for="codec in REDIS_VALUE_CODEC_ORDER"
|
||||||
:key="codec"
|
:key="codec"
|
||||||
@@ -2818,7 +2818,7 @@ defineExpose({ focusSearch });
|
|||||||
>
|
>
|
||||||
{{ redisCodecLabel(codec) }}
|
{{ redisCodecLabel(codec) }}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</RedisHorizontalScrollbar>
|
||||||
<FileArchive v-if="!isStringValueTruncated && stringGzipBadge && stringValueCodec === 'none'" class="h-3.5 w-3.5 shrink-0 text-muted-foreground" :title="t('redis.gzipBadgeTitle')" :aria-label="t('redis.gzipBadgeTitle')" />
|
<FileArchive v-if="!isStringValueTruncated && stringGzipBadge && stringValueCodec === 'none'" class="h-3.5 w-3.5 shrink-0 text-muted-foreground" :title="t('redis.gzipBadgeTitle')" :aria-label="t('redis.gzipBadgeTitle')" />
|
||||||
<span class="flex-1" />
|
<span class="flex-1" />
|
||||||
<label v-if="isTextRedisFormat(stringValueView) || activeStructuredStringDetail || isDecompressCodec(stringValueCodec)" class="flex items-center gap-1.5 text-muted-foreground">
|
<label v-if="isTextRedisFormat(stringValueView) || activeStructuredStringDetail || isDecompressCodec(stringValueCodec)" class="flex items-center gap-1.5 text-muted-foreground">
|
||||||
@@ -2829,7 +2829,7 @@ defineExpose({ focusSearch });
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex h-9 items-center gap-2 border-b px-4 text-xs shrink-0">
|
<div class="flex h-9 items-center gap-2 border-b px-4 text-xs shrink-0">
|
||||||
<span class="shrink-0 text-muted-foreground">{{ t("redis.viewRowLabel") }}</span>
|
<span class="shrink-0 text-muted-foreground">{{ t("redis.viewRowLabel") }}</span>
|
||||||
<div class="flex max-w-full overflow-x-auto rounded-md border bg-muted/20 p-0.5">
|
<RedisHorizontalScrollbar>
|
||||||
<Button
|
<Button
|
||||||
v-for="format in REDIS_VALUE_FORMAT_DISPLAY_ORDER"
|
v-for="format in REDIS_VALUE_FORMAT_DISPLAY_ORDER"
|
||||||
:key="format"
|
:key="format"
|
||||||
@@ -2842,7 +2842,7 @@ defineExpose({ focusSearch });
|
|||||||
>
|
>
|
||||||
{{ redisFormatLabel(format, stringValueDetail.rawLabel) }}
|
{{ redisFormatLabel(format, stringValueDetail.rawLabel) }}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</RedisHorizontalScrollbar>
|
||||||
<span class="flex-1" />
|
<span class="flex-1" />
|
||||||
<div v-if="stringValueView === 'json' && stringValueDetail.json && stringValueCodec === 'none'" class="flex shrink-0 overflow-hidden rounded-md border bg-muted/20 p-0.5">
|
<div v-if="stringValueView === 'json' && stringValueDetail.json && stringValueCodec === 'none'" class="flex shrink-0 overflow-hidden rounded-md border bg-muted/20 p-0.5">
|
||||||
<Button variant="ghost" size="sm" class="h-6 shrink-0 rounded-[5px] px-2 text-xs" :class="{ 'bg-background shadow-sm': !redisJsonDecoded }" @click="setRedisJsonUnicodeMode('raw')">{{ t("redis.jsonViewRaw") }}</Button>
|
<Button variant="ghost" size="sm" class="h-6 shrink-0 rounded-[5px] px-2 text-xs" :class="{ 'bg-background shadow-sm': !redisJsonDecoded }" @click="setRedisJsonUnicodeMode('raw')">{{ t("redis.jsonViewRaw") }}</Button>
|
||||||
@@ -3584,11 +3584,11 @@ defineExpose({ focusSearch });
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="flex h-9 items-center gap-2 border-b px-5 text-xs">
|
<div class="flex h-9 items-center gap-2 border-b px-5 text-xs">
|
||||||
<span class="shrink-0 text-muted-foreground">{{ t("redis.codecRowLabel") }}</span>
|
<span class="shrink-0 text-muted-foreground">{{ t("redis.codecRowLabel") }}</span>
|
||||||
<div class="flex max-w-full overflow-x-auto rounded-md border bg-muted/20 p-0.5">
|
<RedisHorizontalScrollbar>
|
||||||
<Button v-for="codec in REDIS_VALUE_CODEC_ORDER" :key="codec" variant="ghost" size="sm" class="h-6 shrink-0 rounded-[5px] px-2 text-xs" :class="{ 'bg-background shadow-sm': memberValueCodec === codec }" @click="setMemberValueCodec(codec)">
|
<Button v-for="codec in REDIS_VALUE_CODEC_ORDER" :key="codec" variant="ghost" size="sm" class="h-6 shrink-0 rounded-[5px] px-2 text-xs" :class="{ 'bg-background shadow-sm': memberValueCodec === codec }" @click="setMemberValueCodec(codec)">
|
||||||
{{ redisCodecLabel(codec) }}
|
{{ redisCodecLabel(codec) }}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</RedisHorizontalScrollbar>
|
||||||
<span class="flex-1" />
|
<span class="flex-1" />
|
||||||
<label v-if="isTextRedisFormat(memberValueView) || activeStructuredMemberDetail || isDecompressCodec(memberValueCodec)" class="flex items-center gap-1.5 text-muted-foreground">
|
<label v-if="isTextRedisFormat(memberValueView) || activeStructuredMemberDetail || isDecompressCodec(memberValueCodec)" class="flex items-center gap-1.5 text-muted-foreground">
|
||||||
<WrapText class="h-3.5 w-3.5" />
|
<WrapText class="h-3.5 w-3.5" />
|
||||||
@@ -3598,7 +3598,7 @@ defineExpose({ focusSearch });
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex h-9 items-center gap-2 border-b px-5 text-xs">
|
<div class="flex h-9 items-center gap-2 border-b px-5 text-xs">
|
||||||
<span class="shrink-0 text-muted-foreground">{{ t("redis.viewRowLabel") }}</span>
|
<span class="shrink-0 text-muted-foreground">{{ t("redis.viewRowLabel") }}</span>
|
||||||
<div class="flex max-w-full overflow-x-auto rounded-md border bg-muted/20 p-0.5">
|
<RedisHorizontalScrollbar>
|
||||||
<Button
|
<Button
|
||||||
v-for="format in REDIS_VALUE_FORMAT_DISPLAY_ORDER"
|
v-for="format in REDIS_VALUE_FORMAT_DISPLAY_ORDER"
|
||||||
:key="format"
|
:key="format"
|
||||||
@@ -3611,7 +3611,7 @@ defineExpose({ focusSearch });
|
|||||||
>
|
>
|
||||||
{{ redisFormatLabel(format, selectedMemberDetail.rawLabel) }}
|
{{ redisFormatLabel(format, selectedMemberDetail.rawLabel) }}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</RedisHorizontalScrollbar>
|
||||||
<span class="flex-1" />
|
<span class="flex-1" />
|
||||||
<div v-if="memberValueView === 'json' && selectedMemberDetail.json && memberValueCodec === 'none'" class="flex shrink-0 overflow-hidden rounded-md border bg-muted/20 p-0.5">
|
<div v-if="memberValueView === 'json' && selectedMemberDetail.json && memberValueCodec === 'none'" class="flex shrink-0 overflow-hidden rounded-md border bg-muted/20 p-0.5">
|
||||||
<Button variant="ghost" size="sm" class="h-6 shrink-0 rounded-[5px] px-2 text-xs" :class="{ 'bg-background shadow-sm': !redisJsonDecoded }" @click="setRedisJsonUnicodeMode('raw')">{{ t("redis.jsonViewRaw") }}</Button>
|
<Button variant="ghost" size="sm" class="h-6 shrink-0 rounded-[5px] px-2 text-xs" :class="{ 'bg-background shadow-sm': !redisJsonDecoded }" @click="setRedisJsonUnicodeMode('raw')">{{ t("redis.jsonViewRaw") }}</Button>
|
||||||
|
|||||||
@@ -4953,7 +4953,7 @@ export default {
|
|||||||
codecNone: "None",
|
codecNone: "None",
|
||||||
codecRowLabel: "Decode",
|
codecRowLabel: "Decode",
|
||||||
viewRowLabel: "View",
|
viewRowLabel: "View",
|
||||||
codecBase64: "Base64 Decode",
|
codecBase64: "Base64",
|
||||||
unicodeJsonView: "Unicode JSON",
|
unicodeJsonView: "Unicode JSON",
|
||||||
codecMismatch: "Unable to decode with the selected codec; showing the original content",
|
codecMismatch: "Unable to decode with the selected codec; showing the original content",
|
||||||
decompressedView: "Decompressed",
|
decompressedView: "Decompressed",
|
||||||
|
|||||||
@@ -4749,7 +4749,7 @@ export default withEnglishFallback({
|
|||||||
codecNone: "Ninguno",
|
codecNone: "Ninguno",
|
||||||
codecRowLabel: "Descodificar",
|
codecRowLabel: "Descodificar",
|
||||||
viewRowLabel: "Vista",
|
viewRowLabel: "Vista",
|
||||||
codecBase64: "Descodificación Base64",
|
codecBase64: "Base64",
|
||||||
codecMismatch: "No se pudo decodificar con el códec seleccionado; se muestra el contenido original",
|
codecMismatch: "No se pudo decodificar con el códec seleccionado; se muestra el contenido original",
|
||||||
unicodeJsonView: "JSON Unicode",
|
unicodeJsonView: "JSON Unicode",
|
||||||
decompressedView: "Descomprimido",
|
decompressedView: "Descomprimido",
|
||||||
|
|||||||
@@ -4749,7 +4749,7 @@ export default withEnglishFallback({
|
|||||||
codecNone: "Nessuno",
|
codecNone: "Nessuno",
|
||||||
codecRowLabel: "Decodifica",
|
codecRowLabel: "Decodifica",
|
||||||
viewRowLabel: "Vista",
|
viewRowLabel: "Vista",
|
||||||
codecBase64: "Decodifica Base64",
|
codecBase64: "Base64",
|
||||||
codecMismatch: "Impossibile decodificare con il codec selezionato; viene mostrato il contenuto originale",
|
codecMismatch: "Impossibile decodificare con il codec selezionato; viene mostrato il contenuto originale",
|
||||||
unicodeJsonView: "JSON Unicode",
|
unicodeJsonView: "JSON Unicode",
|
||||||
decompressedView: "Decompresso",
|
decompressedView: "Decompresso",
|
||||||
|
|||||||
@@ -4778,7 +4778,7 @@ export default withEnglishFallback({
|
|||||||
codecNone: "なし",
|
codecNone: "なし",
|
||||||
codecRowLabel: "デコード",
|
codecRowLabel: "デコード",
|
||||||
viewRowLabel: "表示",
|
viewRowLabel: "表示",
|
||||||
codecBase64: "Base64 デコード",
|
codecBase64: "Base64",
|
||||||
codecMismatch: "選択したデコード方式では復元できません。元の内容を表示しています",
|
codecMismatch: "選択したデコード方式では復元できません。元の内容を表示しています",
|
||||||
unicodeJsonView: "Unicode JSON",
|
unicodeJsonView: "Unicode JSON",
|
||||||
decompressedView: "解凍ビュー",
|
decompressedView: "解凍ビュー",
|
||||||
|
|||||||
@@ -4375,7 +4375,7 @@ export default withEnglishFallback({
|
|||||||
codecNone: "없음",
|
codecNone: "없음",
|
||||||
codecRowLabel: "디코딩",
|
codecRowLabel: "디코딩",
|
||||||
viewRowLabel: "보기",
|
viewRowLabel: "보기",
|
||||||
codecBase64: "Base64 디코딩",
|
codecBase64: "Base64",
|
||||||
codecMismatch: "선택한 디코딩 방식으로 복원할 수 없어 원본 내용을 표시합니다",
|
codecMismatch: "선택한 디코딩 방식으로 복원할 수 없어 원본 내용을 표시합니다",
|
||||||
unicodeJsonView: "Unicode JSON",
|
unicodeJsonView: "Unicode JSON",
|
||||||
decompressedView: "압축 해제 보기",
|
decompressedView: "압축 해제 보기",
|
||||||
|
|||||||
@@ -4751,7 +4751,7 @@ export default withEnglishFallback({
|
|||||||
codecNone: "Nenhum",
|
codecNone: "Nenhum",
|
||||||
codecRowLabel: "Decodificação",
|
codecRowLabel: "Decodificação",
|
||||||
viewRowLabel: "Visualização",
|
viewRowLabel: "Visualização",
|
||||||
codecBase64: "Decodificação Base64",
|
codecBase64: "Base64",
|
||||||
codecMismatch: "Não foi possível decodificar com o codec selecionado; exibindo o conteúdo original",
|
codecMismatch: "Não foi possível decodificar com o codec selecionado; exibindo o conteúdo original",
|
||||||
unicodeJsonView: "JSON Unicode",
|
unicodeJsonView: "JSON Unicode",
|
||||||
decompressedView: "Descomprimido",
|
decompressedView: "Descomprimido",
|
||||||
|
|||||||
@@ -4950,7 +4950,7 @@ export default withEnglishFallback({
|
|||||||
codecNone: "Yok",
|
codecNone: "Yok",
|
||||||
codecRowLabel: "Çöz",
|
codecRowLabel: "Çöz",
|
||||||
viewRowLabel: "Görünüm",
|
viewRowLabel: "Görünüm",
|
||||||
codecBase64: "Base64 Çöz",
|
codecBase64: "Base64",
|
||||||
unicodeJsonView: "Unicode JSON",
|
unicodeJsonView: "Unicode JSON",
|
||||||
codecMismatch: "Seçili kodekle çözülemedi; özgün içerik gösteriliyor",
|
codecMismatch: "Seçili kodekle çözülemedi; özgün içerik gösteriliyor",
|
||||||
decompressedView: "Sıkıştırma açıldı",
|
decompressedView: "Sıkıştırma açıldı",
|
||||||
|
|||||||
@@ -4937,7 +4937,7 @@ export default withEnglishFallback({
|
|||||||
codecNone: "无",
|
codecNone: "无",
|
||||||
codecRowLabel: "解码",
|
codecRowLabel: "解码",
|
||||||
viewRowLabel: "视图",
|
viewRowLabel: "视图",
|
||||||
codecBase64: "Base64 解码",
|
codecBase64: "Base64",
|
||||||
unicodeJsonView: "Unicode JSON",
|
unicodeJsonView: "Unicode JSON",
|
||||||
codecMismatch: "无法按所选解码方式还原,已显示原始内容",
|
codecMismatch: "无法按所选解码方式还原,已显示原始内容",
|
||||||
decompressedView: "解压视图",
|
decompressedView: "解压视图",
|
||||||
|
|||||||
@@ -4075,7 +4075,7 @@ export default withEnglishFallback({
|
|||||||
codecNone: "無",
|
codecNone: "無",
|
||||||
codecRowLabel: "解碼",
|
codecRowLabel: "解碼",
|
||||||
viewRowLabel: "檢視",
|
viewRowLabel: "檢視",
|
||||||
codecBase64: "Base64 解碼",
|
codecBase64: "Base64",
|
||||||
codecMismatch: "無法按所選解碼方式還原,已顯示原始內容",
|
codecMismatch: "無法按所選解碼方式還原,已顯示原始內容",
|
||||||
unicodeJsonView: "Unicode JSON",
|
unicodeJsonView: "Unicode JSON",
|
||||||
decompressedView: "解壓檢視",
|
decompressedView: "解壓檢視",
|
||||||
|
|||||||
Reference in new issue
Block a user