WIP: feat(VnLog): add descriptors #896
|
@ -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>
|
||||||
|
|
|
@ -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
|
|
||||||
"
|
|
||||||
>,
|
|
||||||
</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"
|
||||||
|
|
|
@ -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,
|
||||||
|
};
|
||||||
|
});
|
Loading…
Reference in New Issue