improve search, fix types
parent
302f435c5d
commit
f9f6d2bca6
|
@ -0,0 +1,47 @@
|
|||
<template>
|
||||
<router-link :to="{name: 'Inspect', params: {'address': result.target}}" class="search-result">
|
||||
<div class="search-result-container">
|
||||
<div class="search-result-key">{{ result.key }}</div>
|
||||
<div class="search-result-value">{{ result.value.c }}</div>
|
||||
</div>
|
||||
</router-link>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {defineComponent, PropType} from "vue";
|
||||
import {IEntry} from "@/types/base";
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
name: "SearchResult",
|
||||
props: {
|
||||
result: {
|
||||
type: Object as PropType<IEntry>,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.search-result {
|
||||
.search-result-container {
|
||||
box-shadow: var(--sl-shadow-medium);
|
||||
margin: .5rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
text-align: center;
|
||||
|
||||
color: #2c3e50;
|
||||
text-decoration: inherit;
|
||||
|
||||
div {
|
||||
margin: .5rem 0;
|
||||
}
|
||||
|
||||
.search-result-key {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,10 +1,10 @@
|
|||
export type Address = string;
|
||||
export type VALUE_TYPE = "VALUE" | "ADDR";
|
||||
export type VALUE_TYPE = "Value" | "Address" | "Invalid";
|
||||
|
||||
export interface IEntry {
|
||||
key: string,
|
||||
target: Address,
|
||||
value: [type: VALUE_TYPE, value: string]
|
||||
key: string,
|
||||
value: {t: VALUE_TYPE, c: string}
|
||||
}
|
||||
|
||||
export interface ListingResult {
|
||||
|
|
|
@ -6,3 +6,12 @@ export async function fetcher(key: string) {
|
|||
throw await response.text();
|
||||
}
|
||||
}
|
||||
|
||||
export function construct(query: string, args: string[]) {
|
||||
let result = query;
|
||||
args.forEach((arg) => {
|
||||
arg = arg.replaceAll("\"", "\\\"");
|
||||
result = result.replace("#", `"${arg}"`);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -3,30 +3,49 @@
|
|||
<sl-input placeholder="Search" v-sl-model:searchQuery>
|
||||
<sl-icon name="search" slot="prefix"></sl-icon>
|
||||
</sl-input>
|
||||
<ul>
|
||||
<li v-for="result in results" :key="result.identity">{{ result }}</li>
|
||||
<ul class="search-results">
|
||||
<li v-for="[identity, result] in Object.entries(results)" :key="identity">
|
||||
<SearchResult :result="result"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {defineComponent} from "vue";
|
||||
import {construct} from "@/utils";
|
||||
import SearchResult from "@/components/SearchResult.vue";
|
||||
import {IEntry} from "@/types/base";
|
||||
|
||||
export default defineComponent({
|
||||
name: "Home",
|
||||
components: {SearchResult},
|
||||
data: () => {
|
||||
return {
|
||||
searchQuery: "",
|
||||
results: []
|
||||
results: {} as { [key: string]: IEntry }
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
async searchQuery() {
|
||||
const response = await fetch(
|
||||
`/api/obj?${new URLSearchParams({query: `(matches ? ? (contains "${this.searchQuery}"))`})}`
|
||||
);
|
||||
const query = construct("(matches ? ? (contains #))", [this.searchQuery]);
|
||||
const response = await fetch(`/api/obj?${new URLSearchParams({query})}`);
|
||||
this.results = await response.json();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.search-results {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
display: block;
|
||||
width: calc(100% / 6);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -5,39 +5,39 @@
|
|||
</h2>
|
||||
<div v-if="!error">
|
||||
<template v-if="attributes.length">
|
||||
<h3>Own attributes ({{ attributes.length }})</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key name</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
<tr v-for="entry in attributes">
|
||||
<td>{{ entry.key }}</td>
|
||||
<td>
|
||||
<Address link v-if="entry.value[0] === 'ADDR'" :address="entry.value[1]"/>
|
||||
<template v-else>
|
||||
{{ entry.value[1] }}
|
||||
</template>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Own attributes ({{ attributes.length }})</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key name</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
<tr v-for="entry in attributes">
|
||||
<td>{{ entry.key }}</td>
|
||||
<td>
|
||||
<Address link v-if="entry.value.t === 'Address'" :address="entry.value.c"/>
|
||||
<template v-else>
|
||||
{{ entry.value.c }}
|
||||
</template>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</template>
|
||||
<template v-if="backlinks.length">
|
||||
<h3>Referred to ({{ backlinks.length }})</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Targets</th>
|
||||
<th>Key names</th>
|
||||
</tr>
|
||||
<tr v-for="entry in backlinks">
|
||||
<td>
|
||||
<Address link :address="entry.target"/>
|
||||
</td>
|
||||
<td>
|
||||
{{ entry.key }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Referred to ({{ backlinks.length }})</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Targets</th>
|
||||
<th>Key names</th>
|
||||
</tr>
|
||||
<tr v-for="entry in backlinks">
|
||||
<td>
|
||||
<Address link :address="entry.target"/>
|
||||
</td>
|
||||
<td>
|
||||
{{ entry.key }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</template>
|
||||
</div>
|
||||
<div v-else class="error">
|
||||
|
@ -69,8 +69,8 @@ export default defineComponent({
|
|||
if (this.data) {
|
||||
const entries = Object.values(this.data) as IEntry[];
|
||||
return entries
|
||||
.sort((a, b) => a.value[1].localeCompare(b.value[1]))
|
||||
.sort((a, b) => a.value[0].localeCompare(b.value[0]))
|
||||
.sort((a, b) => a.value.c.localeCompare(b.value.c))
|
||||
.sort((a, b) => a.value.t.localeCompare(b.value.t))
|
||||
.sort((a, b) => a.key.localeCompare(b.key));
|
||||
} else {
|
||||
return [];
|
||||
|
|
Loading…
Reference in New Issue