WIP: feat(VnLog): add descriptors #896

Draft
alexm wants to merge 1 commits from 6994-vnLog_descriptors into dev
3 changed files with 98 additions and 53 deletions

View File

@ -1,67 +1,86 @@
<script setup> <script setup>
import { watch } from 'vue'; import { watch, computed } from 'vue';
import { toDateString } from 'src/filters'; import { toDateString } from 'src/filters';
import { useDescriptorStore } from 'src/stores/useDescriptorStore';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
const props = defineProps({ const props = defineProps({
value: { type: [String, Number, Boolean, Object], default: undefined }, prop: { type: Object, default: undefined },
}); });
const maxStrLen = 512; const maxStrLen = 512;
let t = ''; let t = '';
let cssClass = ''; let cssClass = '';
let type; let type;
const updateValue = () => { const descriptorStore = useDescriptorStore();
type = typeof props.value;
if (props.value == null) { const propsValue = computed(() => props.prop.val.val);
const updateValue = () => {
type = typeof propsValue.value;
if (propsValue.value == null) {
t = '∅'; t = '∅';
cssClass = 'json-null'; cssClass = 'json-null';
} else { } else {
cssClass = `json-${type}`; cssClass = `json-${type}`;
switch (type) { switch (type) {
case 'number': case 'number':
if (Number.isInteger(props.value)) { if (Number.isInteger(propsValue)) {
t = props.value.toString(); t = propsValue.value.toString();
} else { } else {
t = ( t = (
Math.round((props.value + Number.EPSILON) * 1000) / 1000 Math.round((propsValue.value + Number.EPSILON) * 1000) / 1000
).toString(); ).toString();
} }
break; break;
case 'boolean': case 'boolean':
t = props.value ? '✓' : '✗'; t = propsValue.value ? '✓' : '✗';
cssClass = `json-${props.value ? 'true' : 'false'}`; cssClass = `json-${propsValue.value ? 'true' : 'false'}`;
break; break;
case 'string': case 'string':
t = t =
props.value.length <= maxStrLen propsValue.value.length <= maxStrLen
? props.value ? propsValue
: props.value.substring(0, maxStrLen) + '...'; : propsValue.value.substring(0, maxStrLen) + '...';
break; break;
case 'object': case 'object':
if (props.value instanceof Date) { if (propsValue.value instanceof Date) {
t = toDateString(props.value); t = toDateString(propsValue.value);
} else { } else {
t = props.value.toString(); t = propsValue.value.toString();
} }
break; break;
default: default:
t = props.value.toString(); t = propsValue.value.toString();
} }
} }
}; };
watch(() => props.value, updateValue); watch(() => propsValue.value, updateValue);
updateValue(); updateValue();
</script> </script>
<template> <template>
<span :title="props.prop.name">{{ props.prop.nameI18n }}: </span>
<span <span
:title="type === 'string' && props.value.length > maxStrLen ? props.value : ''" :title="
:class="{ [cssClass]: t !== '' }" type === 'string' && propsValue.value?.length > maxStrLen
? propsValue.value
: ''
"
:class="{
[cssClass]: t !== '',
'json-link': descriptorStore.has(props.prop.name),
}"
> >
{{ t }} {{ t }}
<component
v-if="props.prop.val.id"
:is="descriptorStore.has(props.prop.name)"
:id="props.prop.val.id"
/>
</span> </span>
</template> </template>
@ -85,4 +104,8 @@ updateValue();
color: #cd7c7c; color: #cd7c7c;
font-style: italic; font-style: italic;
} }
.json-link {
text-decoration: underline;
cursor: pointer;
}
</style> </style>

View File

@ -598,33 +598,17 @@ watch(
/> />
<span v-if="log.props.length" class="attributes"> <span v-if="log.props.length" class="attributes">
<span <span
v-if="!log.expand" class="expanded-json q-pa-none"
class="q-pa-none text-grey" :class="
> log.expand
<span ? 'column'
v-for="(prop, propIndex) in log.props" : 'row no-wrap ellipsis'
:key="propIndex" "
class="basic-json" style="
> text-overflow: ellipsis;
<span overflow: hidden;
class="json-field" white-space: nowrap;
:title="prop.name"
>
{{ prop.nameI18n }}:
</span>
<VnJsonValue :value="prop.val.val" />
<span
v-if="
propIndex <
log.props.length - 1
" "
>,&nbsp;
</span>
</span>
</span>
<span
v-if="log.expand"
class="expanded-json column q-pa-none"
> >
<div <div
v-for="( v-for="(
@ -633,20 +617,29 @@ watch(
:key="prop2Index" :key="prop2Index"
class="q-pa-none text-grey" class="q-pa-none text-grey"
> >
<VnJsonValue
:prop="prop"
class="q-pr-xs"
/>
<span <span
class="json-field" v-if="
:title="prop.name" prop2Index < log.props.length
> "
{{ prop.nameI18n }}: class="q-mr-xs"
>,
</span> </span>
<VnJsonValue :value="prop.val.val" />
<span <span
v-if="prop.val.id" v-if="prop.val.id"
class="id-value" class="id-value"
> >
#{{ prop.val.id }} #{{ prop.val.id }}
</span> </span>
<span v-if="log.action == 'update'"> <span
v-if="
log.action == 'update' &&
log.expand
"
>
<VnJsonValue <VnJsonValue
:value="prop.old.val" :value="prop.old.val"

View File

@ -0,0 +1,29 @@
import { ref, defineAsyncComponent } from 'vue';
import { defineStore } from 'pinia';
export const useDescriptorStore = defineStore('descriptorStore', () => {
const descriptors = ref({});
const loaded = ref(false);
function set() {
const files = import.meta.glob(`src/**/*DescriptorProxy.vue`);
for (const file in files) {
descriptors.value[file.split('/').at(-1).slice(0, -19).toLowerCase() + 'Fk'] =
defineAsyncComponent(() => import(file));
}
loaded.value = true;
}
function get() {
if (!loaded.value) set();
}
function has(name) {
get();
return descriptors.value[name];
}
return {
has,
};
});