2021-11-11 23:37:42 +01:00
|
|
|
<script lang="ts">
|
|
|
|
import AttributeView from "./AttributeView.svelte";
|
|
|
|
import { query, useEntity } from "../lib/entity";
|
|
|
|
import Address from "./Address.svelte";
|
|
|
|
import { UpType } from "../lib/types";
|
|
|
|
import type { IEntry } from "upend/types";
|
2021-11-30 23:26:40 +01:00
|
|
|
import BlobPreview from "./BlobPreview.svelte";
|
2021-11-11 23:37:42 +01:00
|
|
|
|
|
|
|
export let address: string;
|
|
|
|
export let editable = false;
|
|
|
|
|
|
|
|
const { error, revalidate, attributes, backlinks } = useEntity(address);
|
|
|
|
|
|
|
|
$: allTypeAddresses = $attributes
|
|
|
|
.map(([_, attr]) => attr)
|
|
|
|
.filter((attr) => attr.attribute == "IS")
|
|
|
|
.map((attr) => attr.value.c);
|
|
|
|
|
|
|
|
$: allTypeEntries = query(
|
|
|
|
() =>
|
|
|
|
`(matches (in ${allTypeAddresses
|
|
|
|
.map((addr) => `"${addr}"`)
|
|
|
|
.join(" ")}) ? ?)`
|
|
|
|
).result;
|
|
|
|
|
|
|
|
let allTypes: { [key: string]: UpType } = {};
|
|
|
|
$: {
|
|
|
|
allTypes = {};
|
|
|
|
$allTypeEntries.forEach(([_, entry]) => {
|
|
|
|
if (allTypes[entry.entity] === undefined) {
|
|
|
|
allTypes[entry.entity] = new UpType(entry.entity);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (entry.attribute) {
|
|
|
|
case "TYPE":
|
|
|
|
allTypes[entry.entity].name = entry.value.c;
|
|
|
|
break;
|
|
|
|
case "TYPE_HAS":
|
|
|
|
case "TYPE_REQUIRES":
|
|
|
|
case "TYPE_ID":
|
|
|
|
allTypes[entry.entity].attributes.push(entry.value.c);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
allTypes = allTypes;
|
|
|
|
}
|
|
|
|
|
|
|
|
let typedAttributes = {} as { [key: string]: [string, IEntry][] };
|
|
|
|
let untypedAttributes = [] as [string, IEntry][];
|
|
|
|
|
|
|
|
$: {
|
|
|
|
typedAttributes = {};
|
|
|
|
untypedAttributes = [];
|
|
|
|
|
|
|
|
$attributes.forEach(([entryAddr, entry]) => {
|
|
|
|
const entryTypes = Object.entries(allTypes).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]);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
typedAttributes = typedAttributes;
|
|
|
|
untypedAttributes = untypedAttributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
$: filteredUntypedAttributes = untypedAttributes.filter(
|
|
|
|
([_, entry]) =>
|
|
|
|
entry.attribute !== "IS" ||
|
|
|
|
!Object.keys(typedAttributes).includes(entry.value.c)
|
|
|
|
);
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<div class="inspect">
|
|
|
|
<h2>
|
2021-12-01 19:59:37 +01:00
|
|
|
<Address {address} />
|
2021-11-11 23:37:42 +01:00
|
|
|
</h2>
|
2021-11-30 23:26:40 +01:00
|
|
|
<BlobPreview {address} />
|
2021-11-11 23:37:42 +01:00
|
|
|
{#if !$error}
|
2021-11-30 00:29:27 +01:00
|
|
|
<div class="attributes">
|
2021-11-11 23:37:42 +01:00
|
|
|
{#each Object.entries(typedAttributes) as [typeAddr, attributes] (typeAddr)}
|
|
|
|
<AttributeView
|
2021-11-30 00:29:27 +01:00
|
|
|
{editable}
|
2021-11-11 23:37:42 +01:00
|
|
|
{address}
|
|
|
|
type={allTypes[typeAddr]}
|
|
|
|
{attributes}
|
|
|
|
on:edit={revalidate}
|
|
|
|
/>
|
|
|
|
{/each}
|
|
|
|
{#if filteredUntypedAttributes.length > 0 || editable}
|
|
|
|
<AttributeView
|
|
|
|
title="Other attributes"
|
|
|
|
{editable}
|
|
|
|
{address}
|
|
|
|
attributes={untypedAttributes}
|
|
|
|
on:change={revalidate}
|
|
|
|
/>
|
|
|
|
{/if}
|
|
|
|
{#if $backlinks.length > 0}
|
|
|
|
<AttributeView
|
|
|
|
title={`Referred to (${$backlinks.length})`}
|
|
|
|
{address}
|
|
|
|
attributes={$backlinks}
|
|
|
|
reverse
|
|
|
|
/>
|
|
|
|
{/if}
|
|
|
|
</div>
|
|
|
|
{:else}
|
|
|
|
<div class="error">
|
|
|
|
{JSON.stringify($error)}
|
|
|
|
</div>
|
|
|
|
{/if}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
2021-11-30 00:29:27 +01:00
|
|
|
.inspect {
|
|
|
|
flex: auto;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
& > * {
|
|
|
|
padding: 0 1rem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.attributes {
|
|
|
|
flex: auto;
|
|
|
|
height: 0; // https://stackoverflow.com/a/14964944
|
|
|
|
overflow-y: auto;
|
|
|
|
}
|
|
|
|
|
2021-11-11 23:37:42 +01:00
|
|
|
.hr {
|
|
|
|
position: relative;
|
|
|
|
margin: 2rem 0 1rem 0;
|
|
|
|
|
|
|
|
hr {
|
|
|
|
border: none;
|
|
|
|
border-top: 4px double var(--foreground);
|
|
|
|
height: 1rem;
|
|
|
|
}
|
|
|
|
|
|
|
|
.hr-label {
|
|
|
|
position: absolute;
|
|
|
|
top: -1ex;
|
|
|
|
left: 50%;
|
|
|
|
transform: translateX(-50%);
|
|
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
|
|
color: var(--foreground);
|
|
|
|
background: var(--background);
|
|
|
|
padding: 0 4px;
|
|
|
|
|
|
|
|
sl-icon {
|
|
|
|
margin-bottom: -4px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.error {
|
|
|
|
color: red;
|
|
|
|
}
|
|
|
|
</style>
|