sort attributes by types, type icons

feat/vaults
Tomáš Mládek 2021-06-19 17:57:09 +02:00
parent 4699d60760
commit cec833ffc4
3 changed files with 81 additions and 34 deletions

15
ui/src/lib/types.ts Normal file
View File

@ -0,0 +1,15 @@
export class UpType {
name: string | null = null;
attributes: string[] = [];
public getIcon(): string | undefined {
return this.name ? TYPE_ICONS[this.name] : undefined;
}
}
const TYPE_ICONS: { [key: string]: string } = {
"BLOB": "box",
"FS_FILE": "file-earmark",
"FS_DIR": "folder"
}

View File

@ -28,8 +28,4 @@ export interface IFile {
export interface VaultInfo {
name: string | null;
location: string;
}
export interface IType {
name?: string;
}

View File

@ -8,21 +8,23 @@
</h2>
<blob-preview :address="address" />
<div v-if="!error">
<template v-if="attributes.length">
<section class="types">
<h3>Types</h3>
<ul>
<li v-for="(type, key) in types" :key="key">
{{ type.name || "???" }}
</li>
</ul>
</section>
<section class="attributes">
<h3>Own attributes ({{ attributes.length }})</h3>
<template v-if="typedAttributes">
<section
class="typed-attribute-list"
v-for="(attributes, typeAddr) in typedAttributes"
:key="typeAddr"
>
<h3>
<sl-icon
v-if="types[typeAddr].getIcon()"
:name="types[typeAddr].getIcon()"
/>
{{ types[typeAddr]?.name || "???" }}
</h3>
<table>
<tr>
<th></th>
<th>Attribute name</th>
<th>Attribute</th>
<th>Value</th>
</tr>
<tr v-for="[id, entry] in attributes" :key="id">
@ -85,8 +87,9 @@
import Address from "@/components/Address.vue";
import BlobPreview from "@/components/BlobPreview.vue";
import { query, useEntity } from "@/lib/entity";
import { IEntry, IType } from "@/types/base";
import { computed, defineComponent } from "vue";
import { UpType } from "@/lib/types";
import { IEntry } from "@/types/base";
import { computed, defineComponent, reactive, watch } from "vue";
export default defineComponent({
name: "Inspect",
@ -154,21 +157,19 @@ export default defineComponent({
);
const allTypes = computed(() => {
const result = {} as { [key: string]: IType };
const result = {} as { [key: string]: UpType };
allTypeEntries.value.forEach(([_, entry]) => {
if (result[entry.entity] === undefined) {
result[entry.entity] = {};
result[entry.entity] = new UpType();
}
switch (entry.attribute) {
case "TYPE":
result[entry.entity].name = entry.value.c;
break;
case "TYPE":
result[entry.entity].name = entry.value.c;
break;
case "TYPE":
result[entry.entity].name = entry.value.c;
case "TYPE_HAS":
case "TYPE_ID":
result[entry.entity].attributes.push(entry.value.c);
break;
}
});
@ -176,8 +177,39 @@ export default defineComponent({
return result;
});
const typedAttributes = reactive(
{} as { [key: string]: [string, IEntry][] }
);
const untypedAttributes = reactive([] as [string, IEntry][]);
watch([attributes, allTypes], () => {
Object.keys(typedAttributes).forEach(
(key) => delete typedAttributes[key]
);
untypedAttributes.length = 0;
attributes.value
.filter(([_, entry]) => entry.attribute !== "IS")
.forEach(([entryAddr, entry]) => {
const entryTypes = Object.entries(allTypes.value).filter(([_, t]) =>
t.attributes.includes(entry.attribute)
);
if (entryTypes.length > 0) {
entryTypes.forEach(([addr, _]) => {
if (typedAttributes[addr] == undefined) {
typedAttributes[addr] = [];
}
typedAttributes[addr].push([entryAddr, entry]);
});
} else {
untypedAttributes.push([entryAddr, entry]);
}
});
});
return {
attributes,
typedAttributes,
untypedAttributes,
backlinks,
error,
mutate,
@ -216,22 +248,26 @@ table {
margin-top: 1.66em;
padding: 1ex 1em;
border: 1px solid var(--foreground);
border-radius: 4px;
h3 {
display: inline-block;
h3 {
display: inline-block;
background: var(--background);
font-weight: 600;
position: absolute;
position: absolute;
top: -1.66em;
left: 0.5ex;
line-height: 1;
padding: 0 0.5ex;
}
left: 1ex;
line-height: 1;
padding: 0 0.75ex;
sl-icon {
margin-bottom: -2px;
}
}
}
.error {