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
Showing only changes of commit 48f1070740 - Show all commits

View File

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

View File

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